<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    .l-title{
      font-size: 60px;
    }
  </style>
</head>
<body>
<div class="l-title">核心概念</div>
<h1>Getting Started - 入门</h1>
<p>在本教程中,你将进行学习 Sequelize 的简单设置.</p>
<h2><a id="user-content-安装" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/getting-started.md#%E5%AE%89%E8%A3%85" aria-hidden="true"></a>安装</h2>
<p>Sequelize 的使用可以通过&nbsp;<a href="https://www.npmjs.com/package/sequelize" rel="nofollow">npm</a>&nbsp;(或&nbsp;<a href="https://yarnpkg.com/package/sequelize" rel="nofollow">yarn</a>).</p>
<div class="highlight highlight-source-shell">
  <pre>npm install --save sequelize</pre>
</div>
<p>你还必须手动为所选数据库安装驱动程序：</p>
<div class="highlight highlight-source-shell">
<pre><span class="pl-c"># 选择以下之一:</span>
$ npm install --save pg pg-hstore <span class="pl-c"># Postgres</span>
$ npm install --save mysql2
$ npm install --save mariadb
$ npm install --save sqlite3
$ npm install --save tedious <span class="pl-c"># Microsoft SQL Server</span></pre>
</div>
<h2><a id="user-content-连接到数据库" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/getting-started.md#%E8%BF%9E%E6%8E%A5%E5%88%B0%E6%95%B0%E6%8D%AE%E5%BA%93" aria-hidden="true"></a>连接到数据库</h2>
<p>要连接到数据库,必须创建一个 Sequelize 实例. 这可以通过将连接参数分别传递到 Sequelize 构造函数或通过传递一个连接 URI 来完成：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> Sequelize <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'sequelize'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 方法 1: 传递一个连接 URI</span>
<span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-s">'sqlite::memory:'</span><span class="pl-kos">)</span> <span class="pl-c">// Sqlite 示例</span>
<span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-s">'postgres://user:pass@example.com:5432/dbname'</span><span class="pl-kos">)</span> <span class="pl-c">// Postgres 示例</span>

<span class="pl-c">// 方法 2: 分别传递参数 (sqlite)</span>
<span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">dialect</span>: <span class="pl-s">'sqlite'</span><span class="pl-kos">,</span>
  <span class="pl-c1">storage</span>: <span class="pl-s">'path/to/database.sqlite'</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 方法 2: 分别传递参数 (其它数据库)</span>
<span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-s">'database'</span><span class="pl-kos">,</span> <span class="pl-s">'username'</span><span class="pl-kos">,</span> <span class="pl-s">'password'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">host</span>: <span class="pl-s">'localhost'</span><span class="pl-kos">,</span>
  <span class="pl-c1">dialect</span>: <span class="pl-c">/* 选择 'mysql' | 'mariadb' | 'postgres' | 'mssql' 其一 */</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>Sequelize 构造函数接受很多参数. 它们记录在&nbsp;<a href="https://sequelize.org/master/class/lib/sequelize.js~Sequelize.html#instance-constructor-constructor" rel="nofollow">API 参考</a>中.</p>
<h3><a id="user-content-测试连接" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/getting-started.md#%E6%B5%8B%E8%AF%95%E8%BF%9E%E6%8E%A5" aria-hidden="true"></a>测试连接</h3>
<p>你可以使用&nbsp;<code>.authenticate()</code>&nbsp;函数测试连接是否正常：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">try</span> <span class="pl-kos">{</span>
  <span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">authenticate</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">'Connection has been established successfully.'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span> <span class="pl-k">catch</span> <span class="pl-kos">(</span><span class="pl-s1">error</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">error</span><span class="pl-kos">(</span><span class="pl-s">'Unable to connect to the database:'</span><span class="pl-kos">,</span> <span class="pl-s1">error</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre>
</div>
<h3><a id="user-content-关闭连接" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/getting-started.md#%E5%85%B3%E9%97%AD%E8%BF%9E%E6%8E%A5" aria-hidden="true"></a>关闭连接</h3>
<p>默认情况下,Sequelize 将保持连接打开状态,并对所有查询使用相同的连接. 如果你需要关闭连接,请调用&nbsp;<code>sequelize.close()</code>(这是异步的并返回一个 Promise).</p>
<h2><a id="user-content-术语约定" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/getting-started.md#%E6%9C%AF%E8%AF%AD%E7%BA%A6%E5%AE%9A" aria-hidden="true"></a>术语约定</h2>
<p>请注意,在上面的示例中,<code>Sequelize</code>&nbsp;是指库本身,而&nbsp;<code>sequelize</code>&nbsp;是指 Sequelize 的实例,它表示与一个数据库的连接. 这是官方推荐的约定,在整个文档中都将遵循.</p>
<h2><a id="user-content-阅读文档的提示" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/getting-started.md#%E9%98%85%E8%AF%BB%E6%96%87%E6%A1%A3%E7%9A%84%E6%8F%90%E7%A4%BA" aria-hidden="true"></a>阅读文档的提示</h2>
<p>我们鼓励你在阅读 Sequelize 文档时在本地运行代码示例. 这将帮助你更快地学习. 最简单的方法是使用 SQLite 方言：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> Sequelize<span class="pl-kos">,</span> Op<span class="pl-kos">,</span> Model<span class="pl-kos">,</span> DataTypes <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">"sequelize"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-s">"sqlite::memory:"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 这是代码! 它是可用的!</span></pre>
</div>
<p>要尝试使用在本地难以设置的其他方言,可以使用&nbsp;<a href="https://github.com/papb/sequelize-sscce">Sequelize SSCCE</a>&nbsp;GitHub 存储库,该库可让你在所有受支持的方言上运行代码, 直接从 GitHub 免费获得,无需任何设置！</p>
<h2><a id="user-content-新数据库与现有数据库" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/getting-started.md#%E6%96%B0%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%8E%E7%8E%B0%E6%9C%89%E6%95%B0%E6%8D%AE%E5%BA%93" aria-hidden="true"></a>新数据库与现有数据库</h2>
<p>如果你是从头开始一个项目,且你的数据库尚不存在,那么一开始就可以使用 Sequelize,以便自动创建数据库中的每个表.</p>
<p>除此之外,如果你想使用 Sequelize 连接到已经充满了表和数据的数据库,那也可以正常工作！ 在两种情况下,Sequelize 都能满足你的要求.</p>
<h2><a id="user-content-记录日志" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/getting-started.md#%E8%AE%B0%E5%BD%95%E6%97%A5%E5%BF%97" aria-hidden="true"></a>记录日志</h2>
<p>默认情况下,Sequelize 将记录控制台执行的每个SQL查询. 可以使用&nbsp;<code>options.logging</code>&nbsp;参数来自定义每次 Sequelize 记录某些内容时将执行的函数. 默认值为&nbsp;<code>console.log</code>,使用该值时仅显示日志函数调用的第一个参数. 例如,对于查询日志记录,第一个参数是原始查询,第二个参数(默认情况下是隐藏的)是 Sequelize 对象.</p>
<p><code>options.logging</code>&nbsp;的常用值：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-s">'sqlite::memory:'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c">// 选择一种日志记录参数</span>
  <span class="pl-c1">logging</span>: <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-c1">log</span><span class="pl-kos">,</span>                  <span class="pl-c">// 默认值,显示日志函数调用的第一个参数</span>
  <span class="pl-en">logging</span>: <span class="pl-kos">(</span>...<span class="pl-s1">msg</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">msg</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-c">// 显示所有日志函数调用参数</span>
  <span class="pl-c1">logging</span>: <span class="pl-c1">false</span><span class="pl-kos">,</span>                        <span class="pl-c">// 禁用日志记录</span>
  <span class="pl-en">logging</span>: <span class="pl-s1">msg</span> <span class="pl-c1">=&gt;</span> <span class="pl-s1">logger</span><span class="pl-kos">.</span><span class="pl-en">debug</span><span class="pl-kos">(</span><span class="pl-s1">msg</span><span class="pl-kos">)</span><span class="pl-kos">,</span>     <span class="pl-c">// 使用自定义记录器(例如Winston 或 Bunyan),显示第一个参数</span>
  <span class="pl-c1">logging</span>: <span class="pl-s1">logger</span><span class="pl-kos">.</span><span class="pl-c1">debug</span><span class="pl-kos">.</span><span class="pl-en">bind</span><span class="pl-kos">(</span><span class="pl-s1">logger</span><span class="pl-kos">)</span>     <span class="pl-c">// 使用自定义记录器的另一种方法,显示所有消息</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h2><a id="user-content-promises-和-asyncawait" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/getting-started.md#promises-%E5%92%8C-asyncawait" aria-hidden="true"></a>Promises 和 async/await</h2>
<p>Sequelize 提供的大多数方法都是异步的,因此返回 Promises. 它们都是&nbsp;<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise" rel="nofollow">Promises</a>, 因此你可以直接使用Promise API(例如,使用&nbsp;<code>then</code>,&nbsp;<code>catch</code>,&nbsp;<code>finally</code>).</p>
<p>当然,使用&nbsp;<code>async</code>&nbsp;和&nbsp;<code>await</code>&nbsp;也可以正常工作.</p>
<p>&nbsp;</p>
<h1>Model Basics - 模型基础</h1>
<p>在本教程中,你将学习 Sequelize 中的模型以及如何使用它们.</p>
<h2><a id="user-content-概念" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#%E6%A6%82%E5%BF%B5" aria-hidden="true"></a>概念</h2>
<p>模型是 Sequelize 的本质. 模型是代表数据库中表的抽象. 在 Sequelize 中,它是一个&nbsp;<a href="https://sequelize.org/master/class/lib/model.js~Model.html" rel="nofollow">Model</a>&nbsp;的扩展类.</p>
<p>该模型告诉 Sequelize 有关它代表的实体的几件事,例如数据库中表的名称以及它具有的列(及其数据类型).</p>
<p>Sequelize 中的模型有一个名称. 此名称不必与它在数据库中表示的表的名称相同. 通常,模型具有单数名称(例如,<code>User</code>),而表具有复数名称(例如,&nbsp;<code>Users</code>),当然这是完全可配置的.</p>
<h2><a id="user-content-模型定义" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#%E6%A8%A1%E5%9E%8B%E5%AE%9A%E4%B9%89" aria-hidden="true"></a>模型定义</h2>
<p>在 Sequelize 中可以用两种等效的方式定义模型：</p>
<ul>
  <li>调用&nbsp;<a href="https://sequelize.org/master/class/lib/sequelize.js~Sequelize.html#instance-method-define" rel="nofollow"><code>sequelize.define(modelName, attributes, options)</code></a></li>
  <li>扩展&nbsp;<a href="https://sequelize.org/master/class/lib/model.js~Model.html" rel="nofollow">Model</a>&nbsp;并调用&nbsp;<a href="https://sequelize.org/master/class/lib/model.js~Model.html#static-method-init" rel="nofollow"><code>init(attributes, options)</code></a></li>
</ul>
<p>定义模型后,可通过其模型名称在&nbsp;<code>sequelize.models</code>&nbsp;中使用该模型.</p>
<p>为了学习一个示例,我们将考虑创建一个代表用户的模型,该模型具有一个&nbsp;<code>firstName</code>&nbsp;和一个&nbsp;<code>lastName</code>. 我们希望将模型称为&nbsp;<code>User</code>,并将其表示的表在数据库中称为&nbsp;<code>Users</code>.</p>
<p>定义该模型的两种方法如下所示. 定义后,我们可以使用&nbsp;<code>sequelize.models.User</code>&nbsp;访问模型.</p>
<h3><a id="user-content-使用-sequelizedefine" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#%E4%BD%BF%E7%94%A8-sequelizedefine" aria-hidden="true"></a>使用&nbsp;<a href="https://sequelize.org/master/class/lib/sequelize.js~Sequelize.html#instance-method-define" rel="nofollow"><code>sequelize.define</code></a>:</h3>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> Sequelize<span class="pl-kos">,</span> DataTypes <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'sequelize'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-s">'sqlite::memory:'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">const</span> <span class="pl-v">User</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'User'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c">// 在这里定义模型属性</span>
  <span class="pl-c1">firstName</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
    <span class="pl-c1">allowNull</span>: <span class="pl-c1">false</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">lastName</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span>
    <span class="pl-c">// allowNull 默认为 true</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c">// 这是其他模型参数</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// `sequelize.define` 会返回模型</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-v">User</span> <span class="pl-c1">===</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-c1">models</span><span class="pl-kos">.</span><span class="pl-c1">User</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// true</span></pre>
</div>
<h3><a id="user-content-扩展-model" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#%E6%89%A9%E5%B1%95-model" aria-hidden="true"></a>扩展&nbsp;<a href="https://sequelize.org/master/class/lib/model.js~Model.html" rel="nofollow">Model</a></h3>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> Sequelize<span class="pl-kos">,</span> DataTypes<span class="pl-kos">,</span> Model <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'sequelize'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-s">'sqlite::memory'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">class</span> <span class="pl-v">User</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>

<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c">// 在这里定义模型属性</span>
  <span class="pl-c1">firstName</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
    <span class="pl-c1">allowNull</span>: <span class="pl-c1">false</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">lastName</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span>
    <span class="pl-c">// allowNull 默认为 true</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c">// 这是其他模型参数</span>
  sequelize<span class="pl-kos">,</span> <span class="pl-c">// 我们需要传递连接实例</span>
  <span class="pl-c1">modelName</span>: <span class="pl-s">'User'</span> <span class="pl-c">// 我们需要选择模型名称</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 定义的模型是类本身</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-v">User</span> <span class="pl-c1">===</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-c1">models</span><span class="pl-kos">.</span><span class="pl-c1">User</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// true</span></pre>
</div>
<p>在内部,<code>sequelize.define</code>&nbsp;调用&nbsp;<code>Model.init</code>,因此两种方法本质上是等效的.</p>
<h2><a id="user-content-表名推断" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#%E8%A1%A8%E5%90%8D%E6%8E%A8%E6%96%AD" aria-hidden="true"></a>表名推断</h2>
<p>请注意,在以上两种方法中,都从未明确定义表名(<code>Users</code>). 但是,给出了模型名称(<code>User</code>).</p>
<p>默认情况下,当未提供表名时,Sequelize 会自动将模型名复数并将其用作表名. 这种复数是通过称为&nbsp;<a href="https://www.npmjs.com/package/inflection" rel="nofollow">inflection</a>&nbsp;的库在后台完成的,因此可以正确计算不规则的复数(例如&nbsp;<code>person -&gt; people</code>).</p>
<p>当然,此行为很容易配置.</p>
<h3><a id="user-content-强制表名称等于模型名称" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#%E5%BC%BA%E5%88%B6%E8%A1%A8%E5%90%8D%E7%A7%B0%E7%AD%89%E4%BA%8E%E6%A8%A1%E5%9E%8B%E5%90%8D%E7%A7%B0" aria-hidden="true"></a>强制表名称等于模型名称</h3>
<p>你可以使用&nbsp;<code>freezeTableName: true</code>&nbsp;参数停止 Sequelize 执行自动复数化. 这样,Sequelize 将推断表名称等于模型名称,而无需进行任何修改：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'User'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c">// ... (属性)</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">freezeTableName</span>: <span class="pl-c1">true</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>上面的示例将创建一个名为&nbsp;<code>User</code>&nbsp;的模型,该模型指向一个也名为&nbsp;<code>User</code>&nbsp;的表.</p>
<p>也可以为 sequelize 实例全局定义此行为：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-s">'sqlite::memory:'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">define</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">freezeTableName</span>: <span class="pl-c1">true</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>这样,所有表将使用与模型名称相同的名称.</p>
<h3><a id="user-content-直接提供表名" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#%E7%9B%B4%E6%8E%A5%E6%8F%90%E4%BE%9B%E8%A1%A8%E5%90%8D" aria-hidden="true"></a>直接提供表名</h3>
<p>你也可以直接直接告诉 Sequelize 表名称：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'User'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c">// ... (属性)</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">tableName</span>: <span class="pl-s">'Employees'</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h2><a id="user-content-模型同步" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#%E6%A8%A1%E5%9E%8B%E5%90%8C%E6%AD%A5" aria-hidden="true"></a>模型同步</h2>
<p>定义模型时,你要告诉 Sequelize 有关数据库中表的一些信息. 但是,如果该表实际上不存在于数据库中怎么办？ 如果存在,但具有不同的列,较少的列或任何其他差异,该怎么办？</p>
<p>这就是模型同步的来源.可以通过调用一个异步函数(返回一个Promise)<a href="https://sequelize.org/master/class/lib/model.js~Model.html#static-method-sync" rel="nofollow"><code>model.sync(options)</code></a>. 通过此调用,Sequelize 将自动对数据库执行 SQL 查询. 请注意,这仅更改数据库中的表,而不更改 JavaScript 端的模型.</p>
<ul>
  <li><code>User.sync()</code>&nbsp;- 如果表不存在,则创建该表(如果已经存在,则不执行任何操作)</li>
  <li><code>User.sync({ force: true })</code>&nbsp;- 将创建表,如果表已经存在,则将其首先删除</li>
  <li><code>User.sync({ alter: true })</code>&nbsp;- 这将检查数据库中表的当前状态(它具有哪些列,它们的数据类型等),然后在表中进行必要的更改以使其与模型匹配.</li>
</ul>
<p>示例:</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">sync</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">force</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">"用户模型表刚刚(重新)创建！"</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h3><a id="user-content-一次同步所有模型" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#%E4%B8%80%E6%AC%A1%E5%90%8C%E6%AD%A5%E6%89%80%E6%9C%89%E6%A8%A1%E5%9E%8B" aria-hidden="true"></a>一次同步所有模型</h3>
<p>你可以使用&nbsp;<a href="https://sequelize.org/master/class/lib/sequelize.js~Sequelize.html#instance-method-sync" rel="nofollow"><code>sequelize.sync()</code></a>&nbsp;自动同步所有模型. 示例：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">sync</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">force</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">"所有模型均已成功同步."</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h3><a id="user-content-删除表" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#%E5%88%A0%E9%99%A4%E8%A1%A8" aria-hidden="true"></a>删除表</h3>
<p>删除与模型相关的表：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">drop</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">"用户表已删除!"</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>删除所有表：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">drop</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">"所有表已删除!"</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h3><a id="user-content-数据库安全检查" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AE%89%E5%85%A8%E6%A3%80%E6%9F%A5" aria-hidden="true"></a>数据库安全检查</h3>
<p>如上所示,<code>sync</code>和<code>drop</code>操作是破坏性的. Sequelize 使用&nbsp;<code>match</code>&nbsp;参数作为附加的安全检查,该检查将接受 RegExp：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-c">// 仅当数据库名称以 '_test' 结尾时,它才会运行.sync()</span>
<span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">sync</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">force</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span> <span class="pl-c1">match</span>: <span class="pl-pds">/_test<span class="pl-cce">$</span>/</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h3><a id="user-content-生产环境同步" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E5%90%8C%E6%AD%A5" aria-hidden="true"></a>生产环境同步</h3>
<p>如上所示,<code>sync({ force: true })</code>&nbsp;和&nbsp;<code>sync({ alter: true })</code>&nbsp;可能是破坏性操作. 因此,不建议将它们用于生产级软件中. 相反,应该在&nbsp;<a href="https://github.com/sequelize/cli">Sequelize CLI</a>&nbsp;的帮助下使用高级概念&nbsp;<a href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/migrations.html">Migrations</a>(迁移) 进行同步.</p>
<h2><a id="user-content-时间戳" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#%E6%97%B6%E9%97%B4%E6%88%B3" aria-hidden="true"></a>时间戳</h2>
<p>默认情况下,Sequelize 使用数据类型&nbsp;<code>DataTypes.DATE</code>&nbsp;自动向每个模型添加&nbsp;<code>createdAt</code>&nbsp;和&nbsp;<code>updatedAt</code>&nbsp;字段. 这些字段会自动进行管理 - 每当你使用Sequelize 创建或更新内容时,这些字段都会被自动设置.&nbsp;<code>createdAt</code>&nbsp;字段将包含代表创建时刻的时间戳,而&nbsp;<code>updatedAt</code>&nbsp;字段将包含最新更新的时间戳.</p>
<p><strong>注意：</strong>&nbsp;这是在 Sequelize 级别完成的(即未使用&nbsp;<em>SQL触发器</em>&nbsp;完成). 这意味着直接 SQL 查询(例如,通过任何其他方式在不使用 Sequelize 的情况下执行的查询)将不会导致这些字段自动更新.</p>
<p>对于带有&nbsp;<code>timestamps: false</code>&nbsp;参数的模型,可以禁用此行为：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'User'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c">// ... (属性)</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>也可以只启用&nbsp;<code>createdAt</code>/<code>updatedAt</code>&nbsp;之一,并为这些列提供自定义名称：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">class</span> <span class="pl-v">Foo</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c">/* 属性 */</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  sequelize<span class="pl-kos">,</span>

  <span class="pl-c">// 不要忘记启用时间戳！</span>
  <span class="pl-c1">timestamps</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>

  <span class="pl-c">// 不想要 createdAt</span>
  <span class="pl-c1">createdAt</span>: <span class="pl-c1">false</span><span class="pl-kos">,</span>

  <span class="pl-c">// 想要 updatedAt 但是希望名称叫做 updateTimestamp</span>
  <span class="pl-c1">updatedAt</span>: <span class="pl-s">'updateTimestamp'</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h2><a id="user-content-列声明简写语法" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#%E5%88%97%E5%A3%B0%E6%98%8E%E7%AE%80%E5%86%99%E8%AF%AD%E6%B3%95" aria-hidden="true"></a>列声明简写语法</h2>
<p>如果关于列的唯一指定内容是其数据类型,则可以缩短语法：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-c">// 例如:</span>
<span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'User'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">name</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 可以简写为:</span>
<span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'User'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h2><a id="user-content-默认值" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#%E9%BB%98%E8%AE%A4%E5%80%BC" aria-hidden="true"></a>默认值</h2>
<p>默认情况下,Sequelize 假定列的默认值为&nbsp;<code>NULL</code>. 可以通过将特定的&nbsp;<code>defaultValue</code>&nbsp;传递给列定义来更改此行为：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'User'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">name</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
    <span class="pl-c1">defaultValue</span>: <span class="pl-s">"John Doe"</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>一些特殊的值,例如&nbsp;<code>Sequelize.NOW</code>,也能被接受：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'Foo'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">bar</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">DATETIME</span><span class="pl-kos">,</span>
    <span class="pl-c1">defaultValue</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">NOW</span>
    <span class="pl-c">// 这样,当前日期/时间将用于填充此列(在插入时)</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h2><a id="user-content-数据类型" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B" aria-hidden="true"></a>数据类型</h2>
<p>你在模型中定义的每一列都必须具有数据类型. Sequelize 提供<a href="https://github.com/sequelize/sequelize/blob/master/lib/data-types.js">很多内置数据类型</a>. 要访问内置数据类型,必须导入&nbsp;<code>DataTypes</code>：</p>
<div class="highlight highlight-source-js">
  <pre><span class="pl-k">const</span> <span class="pl-kos">{</span> DataTypes <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">"sequelize"</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 导入内置数据类型</span></pre>
</div>
<h3><a id="user-content-字符串" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#%E5%AD%97%E7%AC%A6%E4%B8%B2" aria-hidden="true"></a>字符串</h3>
<div class="highlight highlight-source-js">
<pre><span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span>             <span class="pl-c">// VARCHAR(255)</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">STRING</span><span class="pl-kos">(</span><span class="pl-c1">1234</span><span class="pl-kos">)</span>       <span class="pl-c">// VARCHAR(1234)</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">.</span><span class="pl-c1">BINARY</span>      <span class="pl-c">// VARCHAR BINARY</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">TEXT</span>               <span class="pl-c">// TEXT</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">TEXT</span><span class="pl-kos">(</span><span class="pl-s">'tiny'</span><span class="pl-kos">)</span>       <span class="pl-c">// TINYTEXT</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">CITEXT</span>             <span class="pl-c">// CITEXT          仅 PostgreSQL 和 SQLite.</span></pre>
</div>
<h3><a id="user-content-布尔" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#%E5%B8%83%E5%B0%94" aria-hidden="true"></a>布尔</h3>
<div class="highlight highlight-source-js">
  <pre><span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">BOOLEAN</span>            <span class="pl-c">// TINYINT(1)</span></pre>
</div>
<h3><a id="user-content-数字" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#%E6%95%B0%E5%AD%97" aria-hidden="true"></a>数字</h3>
<div class="highlight highlight-source-js">
<pre><span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span>            <span class="pl-c">// INTEGER</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">BIGINT</span>             <span class="pl-c">// BIGINT</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">BIGINT</span><span class="pl-kos">(</span><span class="pl-c1">11</span><span class="pl-kos">)</span>         <span class="pl-c">// BIGINT(11)</span>

<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">FLOAT</span>              <span class="pl-c">// FLOAT</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">FLOAT</span><span class="pl-kos">(</span><span class="pl-c1">11</span><span class="pl-kos">)</span>          <span class="pl-c">// FLOAT(11)</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">FLOAT</span><span class="pl-kos">(</span><span class="pl-c1">11</span><span class="pl-kos">,</span> <span class="pl-c1">10</span><span class="pl-kos">)</span>      <span class="pl-c">// FLOAT(11,10)</span>

<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">REAL</span>               <span class="pl-c">// REAL            仅 PostgreSQL.</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">REAL</span><span class="pl-kos">(</span><span class="pl-c1">11</span><span class="pl-kos">)</span>           <span class="pl-c">// REAL(11)        仅 PostgreSQL.</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">REAL</span><span class="pl-kos">(</span><span class="pl-c1">11</span><span class="pl-kos">,</span> <span class="pl-c1">12</span><span class="pl-kos">)</span>       <span class="pl-c">// REAL(11,12)     仅 PostgreSQL.</span>

<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">DOUBLE</span>             <span class="pl-c">// DOUBLE</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">DOUBLE</span><span class="pl-kos">(</span><span class="pl-c1">11</span><span class="pl-kos">)</span>         <span class="pl-c">// DOUBLE(11)</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">DOUBLE</span><span class="pl-kos">(</span><span class="pl-c1">11</span><span class="pl-kos">,</span> <span class="pl-c1">10</span><span class="pl-kos">)</span>     <span class="pl-c">// DOUBLE(11,10)</span>

<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">DECIMAL</span>            <span class="pl-c">// DECIMAL</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">DECIMAL</span><span class="pl-kos">(</span><span class="pl-c1">10</span><span class="pl-kos">,</span> <span class="pl-c1">2</span><span class="pl-kos">)</span>     <span class="pl-c">// DECIMAL(10,2)</span></pre>
</div>
<h4><a id="user-content-无符号和零填充整数---仅限于mysqlmariadb" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#%E6%97%A0%E7%AC%A6%E5%8F%B7%E5%92%8C%E9%9B%B6%E5%A1%AB%E5%85%85%E6%95%B4%E6%95%B0---%E4%BB%85%E9%99%90%E4%BA%8Emysqlmariadb" aria-hidden="true"></a>无符号和零填充整数 - 仅限于MySQL/MariaDB</h4>
<p>在 MySQL 和 MariaDB 中,可以将数据类型<code>INTEGER</code>,&nbsp;<code>BIGINT</code>,&nbsp;<code>FLOAT</code>&nbsp;和&nbsp;<code>DOUBLE</code>&nbsp;设置为无符号或零填充(或两者),如下所示：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">.</span><span class="pl-c1">UNSIGNED</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">.</span><span class="pl-c1">ZEROFILL</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">.</span><span class="pl-c1">UNSIGNED</span><span class="pl-kos">.</span><span class="pl-c1">ZEROFILL</span>
<span class="pl-c">// 你还可以指定大小,即INTEGER(10)而不是简单的INTEGER</span>
<span class="pl-c">// 同样适用于 BIGINT, FLOAT 和 DOUBLE</span></pre>
</div>
<h3><a id="user-content-日期" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#%E6%97%A5%E6%9C%9F" aria-hidden="true"></a>日期</h3>
<div class="highlight highlight-source-js">
<pre><span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">DATE</span>       <span class="pl-c">// DATETIME 适用于 mysql / sqlite, 带时区的TIMESTAMP 适用于 postgres</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">DATE</span><span class="pl-kos">(</span><span class="pl-c1">6</span><span class="pl-kos">)</span>    <span class="pl-c">// DATETIME(6) 适用于 mysql 5.6.4+. 支持6位精度的小数秒</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">DATEONLY</span>   <span class="pl-c">// 不带时间的 DATE</span></pre>
</div>
<h3><a id="user-content-uuid" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#uuid" aria-hidden="true"></a>UUID</h3>
<p>对于 UUID,使用&nbsp;<code>DataTypes.UUID</code>. 对于 PostgreSQL 和 SQLite,它会是&nbsp;<code>UUID</code>&nbsp;数据类型;对于 MySQL,它则变成<code>CHAR(36)</code>. Sequelize 可以自动为这些字段生成 UUID,只需使用&nbsp;<code>Sequelize.UUIDV1</code>&nbsp;或&nbsp;<code>Sequelize.UUIDV4</code>&nbsp;作为默认值即可：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-kos">{</span>
  <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">UUID</span><span class="pl-kos">,</span>
  <span class="pl-c1">defaultValue</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">UUIDV4</span> <span class="pl-c">// 或 Sequelize.UUIDV1</span>
<span class="pl-kos">}</span></pre>
</div>
<h3><a id="user-content-其它" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#%E5%85%B6%E5%AE%83" aria-hidden="true"></a>其它</h3>
<p>还有其他数据类型,请参见<a href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/other-topics/other-data-types.md">其它数据类型</a>.</p>
<h2><a id="user-content-列参数" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#%E5%88%97%E5%8F%82%E6%95%B0" aria-hidden="true"></a>列参数</h2>
<p>在定义列时,除了指定列的&nbsp;<code>type</code>&nbsp;以及上面提到的&nbsp;<code>allowNull</code>&nbsp;和&nbsp;<code>defaultValue</code>&nbsp;参数外,还有很多可用的参数. 下面是一些示例.</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> Model<span class="pl-kos">,</span> DataTypes<span class="pl-kos">,</span> Deferrable <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">"sequelize"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">class</span> <span class="pl-v">Foo</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c">// 实例化将自动将 flag 设置为 true (如果未设置)</span>
  <span class="pl-c1">flag</span>: <span class="pl-kos">{</span> <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">BOOLEAN</span><span class="pl-kos">,</span> <span class="pl-c1">allowNull</span>: <span class="pl-c1">false</span><span class="pl-kos">,</span> <span class="pl-c1">defaultValue</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>

  <span class="pl-c">// 日期的默认值 =&gt; 当前时间</span>
  <span class="pl-c1">myDate</span>: <span class="pl-kos">{</span> <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">DATE</span><span class="pl-kos">,</span> <span class="pl-c1">defaultValue</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">NOW</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>

  <span class="pl-c">// 将 allowNull 设置为 false 将为该列添加 NOT NULL,</span>
  <span class="pl-c">// 这意味着如果该列为 null,则在执行查询时将从数据库引发错误.</span>
  <span class="pl-c">// 如果要在查询数据库之前检查值是否不为 null,请查看下面的验证部分.</span>
  <span class="pl-c1">title</span>: <span class="pl-kos">{</span> <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span> <span class="pl-c1">allowNull</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>

  <span class="pl-c">// 创建两个具有相同值的对象将引发错误.</span>
  <span class="pl-c">// unique 属性可以是布尔值或字符串.</span>
  <span class="pl-c">// 如果为多个列提供相同的字符串,则它们将形成一个复合唯一键.</span>
  <span class="pl-c1">uniqueOne</span>: <span class="pl-kos">{</span> <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>  <span class="pl-c1">unique</span>: <span class="pl-s">'compositeIndex'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">uniqueTwo</span>: <span class="pl-kos">{</span> <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span> <span class="pl-c1">unique</span>: <span class="pl-s">'compositeIndex'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>

  <span class="pl-c">// unique 属性是创建唯一约束的简写.</span>
  <span class="pl-c1">someUnique</span>: <span class="pl-kos">{</span> <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span> <span class="pl-c1">unique</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>

  <span class="pl-c">// 继续阅读有关主键的更多信息</span>
  <span class="pl-c1">identifier</span>: <span class="pl-kos">{</span> <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span> <span class="pl-c1">primaryKey</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>

  <span class="pl-c">// autoIncrement 可用于创建 auto_incrementing 整数列</span>
  <span class="pl-c1">incrementMe</span>: <span class="pl-kos">{</span> <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span> <span class="pl-c1">autoIncrement</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>

  <span class="pl-c">// 你可以通过 'field' 属性指定自定义列名称：</span>
  <span class="pl-c1">fieldWithUnderscores</span>: <span class="pl-kos">{</span> <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span> <span class="pl-c1">field</span>: <span class="pl-s">'field_with_underscores'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>

  <span class="pl-c">// 可以创建外键：</span>
  <span class="pl-c1">bar_id</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>

    <span class="pl-c1">references</span>: <span class="pl-kos">{</span>
      <span class="pl-c">// 这是对另一个模型的参考</span>
      <span class="pl-c1">model</span>: <span class="pl-v">Bar</span><span class="pl-kos">,</span>

      <span class="pl-c">// 这是引用模型的列名</span>
      <span class="pl-c1">key</span>: <span class="pl-s">'id'</span><span class="pl-kos">,</span>

      <span class="pl-c">// 使用 PostgreSQL,可以通过 Deferrable 类型声明何时检查外键约束.</span>
      <span class="pl-c1">deferrable</span>: <span class="pl-v">Deferrable</span><span class="pl-kos">.</span><span class="pl-c1">INITIALLY_IMMEDIATE</span>
      <span class="pl-c">// 参数:</span>
      <span class="pl-c">// - `Deferrable.INITIALLY_IMMEDIATE` - 立即检查外键约束</span>
      <span class="pl-c">// - `Deferrable.INITIALLY_DEFERRED` - 将所有外键约束检查推迟到事务结束</span>
      <span class="pl-c">// - `Deferrable.NOT` - 完全不推迟检查(默认) - 这将不允许你动态更改事务中的规则</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>

  <span class="pl-c">// 注释只能添加到 MySQL,MariaDB,PostgreSQL 和 MSSQL 的列中</span>
  <span class="pl-c1">commentMe</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
    <span class="pl-c1">comment</span>: <span class="pl-s">'这是带有注释的列'</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  sequelize<span class="pl-kos">,</span>
  <span class="pl-c1">modelName</span>: <span class="pl-s">'foo'</span><span class="pl-kos">,</span>

  <span class="pl-c">// 在上面的属性中使用 `unique: true` 与在模型的参数中创建索引完全相同：</span>
  <span class="pl-c1">indexes</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span> <span class="pl-c1">unique</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span> <span class="pl-c1">fields</span>: <span class="pl-kos">[</span><span class="pl-s">'someUnique'</span><span class="pl-kos">]</span> <span class="pl-kos">}</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h2><a id="user-content-利用模型作为类" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md#%E5%88%A9%E7%94%A8%E6%A8%A1%E5%9E%8B%E4%BD%9C%E4%B8%BA%E7%B1%BB" aria-hidden="true"></a>利用模型作为类</h2>
<p>Sequelize 模型是&nbsp;<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes" rel="nofollow">ES6 类</a>. 你可以非常轻松地添加自定义实例或类级别的方法.</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">class</span> <span class="pl-v">User</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span>
  <span class="pl-k">static</span> <span class="pl-en">classLevelMethod</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-s">'foo'</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
  <span class="pl-en">instanceLevelMethod</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-s">'bar'</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
  <span class="pl-en">getFullname</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-kos">[</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">firstname</span><span class="pl-kos">,</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">lastname</span><span class="pl-kos">]</span><span class="pl-kos">.</span><span class="pl-en">join</span><span class="pl-kos">(</span><span class="pl-s">' '</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">firstname</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">TEXT</span><span class="pl-kos">,</span>
  <span class="pl-c1">lastname</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">TEXT</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> sequelize <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">classLevelMethod</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 'foo'</span>
<span class="pl-k">const</span> <span class="pl-s1">user</span> <span class="pl-c1">=</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">build</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">firstname</span>: <span class="pl-s">'Jane'</span><span class="pl-kos">,</span> <span class="pl-c1">lastname</span>: <span class="pl-s">'Doe'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-en">instanceLevelMethod</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 'bar'</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-en">getFullname</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 'Jane Doe'<br /></span></pre>
  <h1>Model Instances - 模型实例</h1>
  <p>如你所知,模型是&nbsp;<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes" rel="nofollow">ES6 类</a>. 类的实例表示该模型中的一个对象(该对象映射到数据库中表的一行). 这样,模型实例就是&nbsp;<a href="https://en.wikipedia.org/wiki/Data_access_object" rel="nofollow">DAOs</a></p>
  <p>对于本指南,将假定以下设置：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> Sequelize<span class="pl-kos">,</span> Model<span class="pl-kos">,</span> DataTypes <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">"sequelize"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-s">"sqlite::memory:"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">const</span> <span class="pl-v">User</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">"user"</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">TEXT</span><span class="pl-kos">,</span>
  <span class="pl-c1">favoriteColor</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">TEXT</span><span class="pl-kos">,</span>
    <span class="pl-c1">defaultValue</span>: <span class="pl-s">'green'</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">age</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
  <span class="pl-c1">cash</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-kos">(</span><span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">sync</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">force</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-c">// 这里是代码</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h2>创建实例</h2>
  <p>尽管模型是一个类,但是你不应直接使用&nbsp;<code>new</code>&nbsp;运算符来创建实例. 相反,应该使用&nbsp;<a href="https://sequelize.org/master/class/lib/model.js~Model.html#static-method-build" rel="nofollow"><code>build</code></a>&nbsp;方法：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">jane</span> <span class="pl-c1">=</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">build</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">"Jane"</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">jane</span> <span class="pl-k">instanceof</span> <span class="pl-v">User</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// true</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// "Jane"</span></pre>
  </div>
  <p>但是,以上代码根本无法与数据库通信(请注意,它甚至不是异步的)！ 这是因为&nbsp;<a href="https://sequelize.org/master/class/lib/model.js~Model.html#static-method-build" rel="nofollow"><code>build</code></a>&nbsp;方法仅创建一个对象,该对象&nbsp;<em>表示</em>&nbsp;<em>可以</em>&nbsp;映射到数据库的数据. 为了将这个实例真正保存(即持久保存)在数据库中,应使用&nbsp;<a href="https://sequelize.org/master/class/lib/model.js~Model.html#instance-method-save" rel="nofollow"><code>save</code></a>&nbsp;方法：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">await</span> <span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-en">save</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">'Jane 已保存到数据库!'</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>请注意,从上面代码段中的&nbsp;<code>await</code>&nbsp;用法来看,<code>save</code>&nbsp;是一种异步方法. 实际上,几乎每个 Sequelize 方法都是异步的.&nbsp;<code>build</code>&nbsp;是极少数例外之一.</p>
  <h3>非常有用的捷径:&nbsp;<code>create</code>&nbsp;方法</h3>
  <p>Sequelize提供了&nbsp;<a href="https://sequelize.org/master/class/lib/model.js~Model.html#static-method-create" rel="nofollow"><code>create</code></a>&nbsp;方法,该方法将上述的&nbsp;<code>build</code>&nbsp;方法和&nbsp;<code>save</code>&nbsp;方法合并为一个方法：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">jane</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">"Jane"</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// Jane 现在存在于数据库中！</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">jane</span> <span class="pl-k">instanceof</span> <span class="pl-v">User</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// true</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// "Jane"</span></pre>
  </div>
  <h2>注意: 实例记录</h2>
  <p>尝试将模型实例直接记录到&nbsp;<code>console.log</code>&nbsp;会产生很多问题,因为 Sequelize 实例具有很多附加条件. 相反,你可以使用&nbsp;<code>.toJSON()</code>&nbsp;方法(顺便说一句,它会自动保证实例被&nbsp;<code>JSON.stringify</code>&nbsp;编辑好).</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">jane</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">"Jane"</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// console.log(jane); // 不要这样!</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-en">toJSON</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 这样最好!</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-c1">JSON</span><span class="pl-kos">.</span><span class="pl-en">stringify</span><span class="pl-kos">(</span><span class="pl-s1">jane</span><span class="pl-kos">,</span> <span class="pl-c1">null</span><span class="pl-kos">,</span> <span class="pl-c1">4</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 这样也不错!</span></pre>
  </div>
  <h2>默认值</h2>
  <p>内置实例将自动获得默认值：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">jane</span> <span class="pl-c1">=</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">build</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">"Jane"</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-c1">favoriteColor</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// "green"</span></pre>
  </div>
  <h2>更新实例</h2>
  <p>如果你更改实例的某个字段的值,则再次调用&nbsp;<code>save</code>&nbsp;将相应地对其进行更新：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">jane</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">"Jane"</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// "Jane"</span>
<span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-c1">name</span> <span class="pl-c1">=</span> <span class="pl-s">"Ada"</span><span class="pl-kos">;</span>
<span class="pl-c">// 数据库中的名称仍然是 "Jane"</span>
<span class="pl-k">await</span> <span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-en">save</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 现在该名称已在数据库中更新为 "Ada"！</span></pre>
  </div>
  <h2>删除实例</h2>
  <p>你可以通过调用&nbsp;<a href="https://sequelize.org/master/class/lib/model.js~Model.html#instance-method-destroy" rel="nofollow"><code>destroy</code></a>&nbsp;来删除实例:</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">jane</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">"Jane"</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// "Jane"</span>
<span class="pl-k">await</span> <span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-en">destroy</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 现在该条目已从数据库中删除</span></pre>
  </div>
  <h2>重载实例</h2>
  <p>你可以通过调用&nbsp;<a href="https://sequelize.org/master/class/lib/model.js~Model.html#instance-method-reload" rel="nofollow"><code>reload</code></a>&nbsp;从数据库中重新加载实例:</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">jane</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">"Jane"</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// "Jane"</span>
<span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-c1">name</span> <span class="pl-c1">=</span> <span class="pl-s">"Ada"</span><span class="pl-kos">;</span>
<span class="pl-c">// 数据库中的名称依然是 "Jane"</span>
<span class="pl-k">await</span> <span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-en">reload</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// "Jane"</span></pre>
  </div>
  <p>reload 调用生成一个&nbsp;<code>SELECT</code>&nbsp;查询,以从数据库中获取最新数据.</p>
  <h2>仅保存部分字段</h2>
  <p>通过传递一个列名数组,可以定义在调用&nbsp;<code>save</code>&nbsp;时应该保存哪些属性.</p>
  <p>当你基于先前定义的对象设置属性时,例如,当你通过 Web 应用程序的形式获取对象的值时,这很有用. 此外,这在&nbsp;<code>update</code>&nbsp;实现中内部使用. 它是这样的：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">jane</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">"Jane"</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// "Jane"</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-c1">favoriteColor</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// "green"</span>
<span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-c1">name</span> <span class="pl-c1">=</span> <span class="pl-s">"Jane II"</span><span class="pl-kos">;</span>
<span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-c1">favoriteColor</span> <span class="pl-c1">=</span> <span class="pl-s">"blue"</span><span class="pl-kos">;</span>
<span class="pl-k">await</span> <span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-en">save</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">fields</span>: <span class="pl-kos">[</span><span class="pl-s">'name'</span><span class="pl-kos">]</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// "Jane II"</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-c1">favoriteColor</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// "blue"</span>
<span class="pl-c">// 上面显示为 "blue",因为本地对象将其设置为 "blue",</span>
<span class="pl-c">// 但是在数据库中它仍然是 "green"：</span>
<span class="pl-k">await</span> <span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-en">reload</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// "Jane II"</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-c1">favoriteColor</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// "green"</span></pre>
  </div>
  <h2>Change-awareness of save</h2>
  <p>The&nbsp;<code>save</code>&nbsp;method is optimized internally to only update fields that really changed. This means that if you don't change anything and call&nbsp;<code>save</code>, Sequelize will know that the save is superfluous and do nothing, i.e., no query will be generated (it will still return a Promise, but it will resolve immediately).</p>
  <p>Also, if only a few attributes have changed when you call&nbsp;<code>save</code>, only those fields will be sent in the&nbsp;<code>UPDATE</code>&nbsp;query, to improve performance.</p>
  <h2>递增和递减整数值</h2>
  <p>为了递增/递减实例的值而不会遇到并发问题,Sequelize提供了&nbsp;<a href="https://sequelize.org/master/class/lib/model.js~Model.html#instance-method-increment" rel="nofollow"><code>increment</code></a>&nbsp;和&nbsp;<a href="https://sequelize.org/master/class/lib/model.js~Model.html#instance-method-decrement" rel="nofollow"><code>decrement</code></a>&nbsp;实例方法.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">jane</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">"Jane"</span><span class="pl-kos">,</span> <span class="pl-c1">age</span>: <span class="pl-c1">100</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">incrementResult</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-en">increment</span><span class="pl-kos">(</span><span class="pl-s">'age'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">by</span>: <span class="pl-c1">2</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 注意: 如只增加 1, 你可以省略 'by' 参数, 只需执行 `user.increment('age')`</span>

<span class="pl-c">// 在 PostgreSQL 中, 除非设置了 `{returning：false}` 参数(不然它将是 undefined),</span>
<span class="pl-c">// 否则 `incrementResult` 将是更新后的 user.</span>

<span class="pl-c">// 在其它数据库方言中, `incrementResult` 将会是 undefined. 如果你需要更新的实例, 你需要调用 `user.reload()`.</span></pre>
  </div>
  <p>你也可以一次递增多个字段：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">jane</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">"Jane"</span><span class="pl-kos">,</span> <span class="pl-c1">age</span>: <span class="pl-c1">100</span><span class="pl-kos">,</span> <span class="pl-c1">cash</span>: <span class="pl-c1">5000</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">await</span> <span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-en">increment</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-s">'age'</span>: <span class="pl-c1">2</span><span class="pl-kos">,</span>
  <span class="pl-s">'cash'</span>: <span class="pl-c1">100</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 如果值增加相同的数量,则也可以使用以下其他语法：</span>
<span class="pl-k">await</span> <span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-en">increment</span><span class="pl-kos">(</span><span class="pl-kos">[</span><span class="pl-s">'age'</span><span class="pl-kos">,</span> <span class="pl-s">'cash'</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">by</span>: <span class="pl-c1">2</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>递减的工作原理完全相同.</p>
  <pre><span class="pl-c"><br /><br /></span></pre>
  <h1>Model Querying - Basics - 模型查询(基础)</h1>
  <p>Sequelize 提供了多种方法来协助查询数据库中的数据.</p>
  <p><em>重要说明：要使用 Sequelize 执行生产级别的查询,请确保你还阅读了<a href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/other-topics/transactions.md">事务指南</a>. 事务对于确保数据完整性和提供其它好处很重要.</em></p>
  <p>本指南将说明如何进行标准的&nbsp;<a href="https://en.wikipedia.org/wiki/Create,_read,_update_and_delete" rel="nofollow">增删改查(CRUD)</a>&nbsp;查询.</p>
  <h2>简单 INSERT 查询</h2>
  <p>首先,一个简单的例子：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 创建一个新用户</span>
<span class="pl-k">const</span> <span class="pl-s1">jane</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">firstName</span>: <span class="pl-s">"Jane"</span><span class="pl-kos">,</span> <span class="pl-c1">lastName</span>: <span class="pl-s">"Doe"</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">"Jane's auto-generated ID:"</span><span class="pl-kos">,</span> <span class="pl-s1">jane</span><span class="pl-kos">.</span><span class="pl-c1">id</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p><a href="https://sequelize.org/master/class/lib/model.js~Model.html#static-method-create" rel="nofollow"><code>Model.create()</code></a>&nbsp;方法是使用&nbsp;<a href="https://sequelize.org/master/class/lib/model.js~Model.html#static-method-build" rel="nofollow"><code>Model.build()</code></a>&nbsp;构建未保存实例并使用&nbsp;<a href="https://sequelize.org/master/class/lib/model.js~Model.html#instance-method-save" rel="nofollow"><code>instance.save()</code></a>&nbsp;保存实例的简写形式.</p>
  <p>也可以定义在&nbsp;<code>create</code>&nbsp;方法中的属性. 如果你基于用户填写的表单创建数据库条目,这将特别有用. 例如,使用它可以允许你将&nbsp;<code>User</code>&nbsp;模型限制为仅设置用户名和地址,而不设置管理员标志：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">user</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">username</span>: <span class="pl-s">'alice123'</span><span class="pl-kos">,</span>
  <span class="pl-c1">isAdmin</span>: <span class="pl-c1">true</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">fields</span>: <span class="pl-kos">[</span><span class="pl-s">'username'</span><span class="pl-kos">]</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 假设 isAdmin 的默认值为 false</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-c1">username</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 'alice123'</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-c1">isAdmin</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// false</span></pre>
  </div>
  <h2>简单 SELECT 查询</h2>
  <p>你可以使用&nbsp;<a href="https://sequelize.org/master/class/lib/model.js~Model.html#static-method-findAll" rel="nofollow"><code>findAll</code></a>&nbsp;方法从数据库中读取整个表：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 查询所有用户</span>
<span class="pl-k">const</span> <span class="pl-s1">users</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">users</span><span class="pl-kos">.</span><span class="pl-en">every</span><span class="pl-kos">(</span><span class="pl-s1">user</span> <span class="pl-c1">=&gt;</span> <span class="pl-s1">user</span> <span class="pl-k">instanceof</span> <span class="pl-v">User</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// true</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">"All users:"</span><span class="pl-kos">,</span> <span class="pl-c1">JSON</span><span class="pl-kos">.</span><span class="pl-en">stringify</span><span class="pl-kos">(</span><span class="pl-s1">users</span><span class="pl-kos">,</span> <span class="pl-c1">null</span><span class="pl-kos">,</span> <span class="pl-c1">2</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <div class="highlight highlight-source-sql">
    <pre><span class="pl-k">SELECT</span> <span class="pl-k">*</span> <span class="pl-k">FROM</span> ...</pre>
  </div>
  <h2>SELECT 查询特定属性</h2>
  <p>选择某些特定属性,可以使用&nbsp;<code>attributes</code>&nbsp;参数：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Model</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">attributes</span>: <span class="pl-kos">[</span><span class="pl-s">'foo'</span><span class="pl-kos">,</span> <span class="pl-s">'bar'</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <div class="highlight highlight-source-sql">
    <pre><span class="pl-k">SELECT</span> foo, bar <span class="pl-k">FROM</span> ...</pre>
  </div>
  <p>可以使用嵌套数组来重命名属性：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Model</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">attributes</span>: <span class="pl-kos">[</span><span class="pl-s">'foo'</span><span class="pl-kos">,</span> <span class="pl-kos">[</span><span class="pl-s">'bar'</span><span class="pl-kos">,</span> <span class="pl-s">'baz'</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-s">'qux'</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <div class="highlight highlight-source-sql">
    <pre><span class="pl-k">SELECT</span> foo, bar <span class="pl-k">AS</span> baz, qux <span class="pl-k">FROM</span> ...</pre>
  </div>
  <p>你可以使用&nbsp;<a href="https://sequelize.org/master/class/lib/sequelize.js~Sequelize.html#static-method-fn" rel="nofollow"><code>sequelize.fn</code></a>&nbsp;进行聚合：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Model</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">attributes</span>: <span class="pl-kos">[</span>
    <span class="pl-s">'foo'</span><span class="pl-kos">,</span>
    <span class="pl-kos">[</span><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">fn</span><span class="pl-kos">(</span><span class="pl-s">'COUNT'</span><span class="pl-kos">,</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">col</span><span class="pl-kos">(</span><span class="pl-s">'hats'</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">'n_hats'</span><span class="pl-kos">]</span>
    <span class="pl-s">'bar'</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <div class="highlight highlight-source-sql">
    <pre><span class="pl-k">SELECT</span> foo, <span class="pl-c1">COUNT</span>(hats) <span class="pl-k">AS</span> n_hats, bar <span class="pl-k">FROM</span> ...</pre>
  </div>
  <p>使用聚合函数时,必须为它提供一个别名,以便能够从模型中访问它. 在上面的示例中,你可以通过&nbsp;<code>instance.n_hats</code>&nbsp;获取帽子数量.</p>
  <p>有时,如果只想添加聚合,那么列出模型的所有属性可能会很麻烦：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 这是获取帽子数量的烦人方法(每列都有)</span>
<span class="pl-v">Model</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">attributes</span>: <span class="pl-kos">[</span>
    <span class="pl-s">'id'</span><span class="pl-kos">,</span> <span class="pl-s">'foo'</span><span class="pl-kos">,</span> <span class="pl-s">'bar'</span><span class="pl-kos">,</span> <span class="pl-s">'baz'</span><span class="pl-kos">,</span> <span class="pl-s">'qux'</span><span class="pl-kos">,</span> <span class="pl-s">'hats'</span><span class="pl-kos">,</span> <span class="pl-c">// 我们必须列出所有属性...</span>
    <span class="pl-kos">[</span><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">fn</span><span class="pl-kos">(</span><span class="pl-s">'COUNT'</span><span class="pl-kos">,</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">col</span><span class="pl-kos">(</span><span class="pl-s">'hats'</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">'n_hats'</span><span class="pl-kos">]</span> <span class="pl-c">// 添加聚合...</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 这个更短,并且更不易出错. 如果以后在模型中添加/删除属性,它仍然可以正常工作</span>
<span class="pl-v">Model</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">attributes</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">include</span>: <span class="pl-kos">[</span>
      <span class="pl-kos">[</span><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">fn</span><span class="pl-kos">(</span><span class="pl-s">'COUNT'</span><span class="pl-kos">,</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">col</span><span class="pl-kos">(</span><span class="pl-s">'hats'</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">'n_hats'</span><span class="pl-kos">]</span>
    <span class="pl-kos">]</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <div class="highlight highlight-source-sql">
    <pre><span class="pl-k">SELECT</span> id, foo, bar, baz, qux, hats, <span class="pl-c1">COUNT</span>(hats) <span class="pl-k">AS</span> n_hats <span class="pl-k">FROM</span> ...</pre>
  </div>
  <p>同样,也可以排除某些属性：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Model</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">attributes</span>: <span class="pl-kos">{</span> <span class="pl-c1">exclude</span>: <span class="pl-kos">[</span><span class="pl-s">'baz'</span><span class="pl-kos">]</span> <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <div class="highlight highlight-source-sql">
<pre><span class="pl-c">-- Assuming all columns are 'id', 'foo', 'bar', 'baz' and 'qux'</span>
<span class="pl-k">SELECT</span> id, foo, bar, qux <span class="pl-k">FROM</span> ...</pre>
  </div>
  <h2>应用 WHERE 子句</h2>
  <p><code>where</code>&nbsp;参数用于过滤查询.<code>where</code>&nbsp;子句有很多运算符,可以从&nbsp;<a href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/variable/index.html#static-variable-Op"><code>Op</code></a>&nbsp;中以 Symbols 的形式使用.</p>
  <h3>基础</h3>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">authorId</span>: <span class="pl-c1">2</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// SELECT * FROM post WHERE authorId = 2</span></pre>
  </div>
  <p>可以看到没有显式传递任何运算符(来自<code>Op</code>),因为默认情况下 Sequelize 假定进行相等比较. 上面的代码等效于：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> Op <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">"sequelize"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">authorId</span>: <span class="pl-kos">{</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">eq</span><span class="pl-kos">]</span>: <span class="pl-c1">2</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// SELECT * FROM post WHERE authorId = 2</span></pre>
  </div>
  <p>可以传递多个校验:</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">authorId</span>: <span class="pl-c1">12</span>
    <span class="pl-s1">status</span>: <span class="pl-s">'active'</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// SELECT * FROM post WHERE authorId = 12 AND status = 'active';</span></pre>
  </div>
  <p>就像在第一个示例中 Sequelize 推断出&nbsp;<code>Op.eq</code>&nbsp;运算符一样,在这里 Sequelize 推断出调用者希望对两个检查使用&nbsp;<code>AND</code>. 上面的代码等效于：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> Op <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">"sequelize"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">and</span><span class="pl-kos">]</span>: <span class="pl-kos">[</span>
      <span class="pl-kos">{</span> <span class="pl-c1">authorId</span>: <span class="pl-c1">12</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
      <span class="pl-kos">{</span> <span class="pl-c1">status</span>: <span class="pl-s">'active'</span> <span class="pl-kos">}</span>
    <span class="pl-kos">]</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// SELECT * FROM post WHERE authorId = 12 AND status = 'active';</span></pre>
  </div>
  <p><code>OR</code>&nbsp;可以通过类似的方式轻松执行：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> Op <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">"sequelize"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">or</span><span class="pl-kos">]</span>: <span class="pl-kos">[</span>
      <span class="pl-kos">{</span> <span class="pl-c1">authorId</span>: <span class="pl-c1">12</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
      <span class="pl-kos">{</span> <span class="pl-c1">authorId</span>: <span class="pl-c1">13</span> <span class="pl-kos">}</span>
    <span class="pl-kos">]</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// SELECT * FROM post WHERE authorId = 12 OR authorId = 13;</span></pre>
  </div>
  <p>由于以上的&nbsp;<code>OR</code>&nbsp;涉及相同字段 ,因此 Sequelize 允许你使用稍有不同的结构,该结构更易读并且作用相同：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> Op <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">"sequelize"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">destroy</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">authorId</span>: <span class="pl-kos">{</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">or</span><span class="pl-kos">]</span>: <span class="pl-kos">[</span><span class="pl-c1">12</span><span class="pl-kos">,</span> <span class="pl-c1">13</span><span class="pl-kos">]</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// DELETE FROM post WHERE authorId = 12 OR authorId = 13;</span></pre>
  </div>
  <h3>操作符</h3>
  <p>Sequelize 提供了多种运算符.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> Op <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">"sequelize"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">and</span><span class="pl-kos">]</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span> <span class="pl-c1">a</span>: <span class="pl-c1">5</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">b</span>: <span class="pl-c1">6</span> <span class="pl-kos">}</span><span class="pl-kos">]</span><span class="pl-kos">,</span>            <span class="pl-c">// (a = 5) AND (b = 6)</span>
    <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">or</span><span class="pl-kos">]</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span> <span class="pl-c1">a</span>: <span class="pl-c1">5</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">b</span>: <span class="pl-c1">6</span> <span class="pl-kos">}</span><span class="pl-kos">]</span><span class="pl-kos">,</span>             <span class="pl-c">// (a = 5) OR (b = 6)</span>
    <span class="pl-c1">someAttribute</span>: <span class="pl-kos">{</span>
      <span class="pl-c">// 基本</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">eq</span><span class="pl-kos">]</span>: <span class="pl-c1">3</span><span class="pl-kos">,</span>                              <span class="pl-c">// = 3</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">ne</span><span class="pl-kos">]</span>: <span class="pl-c1">20</span><span class="pl-kos">,</span>                             <span class="pl-c">// != 20</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">is</span><span class="pl-kos">]</span>: <span class="pl-c1">null</span><span class="pl-kos">,</span>                           <span class="pl-c">// IS NULL</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">not</span><span class="pl-kos">]</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>                          <span class="pl-c">// IS NOT TRUE</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">or</span><span class="pl-kos">]</span>: <span class="pl-kos">[</span><span class="pl-c1">5</span><span class="pl-kos">,</span> <span class="pl-c1">6</span><span class="pl-kos">]</span><span class="pl-kos">,</span>                         <span class="pl-c">// (someAttribute = 5) OR (someAttribute = 6)</span>

      <span class="pl-c">// 使用方言特定的列标识符 (以下示例中使用 PG):</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">col</span><span class="pl-kos">]</span>: <span class="pl-s">'user.organization_id'</span><span class="pl-kos">,</span>        <span class="pl-c">// = "user"."organization_id"</span>

      <span class="pl-c">// 数字比较</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">gt</span><span class="pl-kos">]</span>: <span class="pl-c1">6</span><span class="pl-kos">,</span>                              <span class="pl-c">// &gt; 6</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">gte</span><span class="pl-kos">]</span>: <span class="pl-c1">6</span><span class="pl-kos">,</span>                             <span class="pl-c">// &gt;= 6</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">lt</span><span class="pl-kos">]</span>: <span class="pl-c1">10</span><span class="pl-kos">,</span>                             <span class="pl-c">// &lt; 10</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">lte</span><span class="pl-kos">]</span>: <span class="pl-c1">10</span><span class="pl-kos">,</span>                            <span class="pl-c">// &lt;= 10</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">between</span><span class="pl-kos">]</span>: <span class="pl-kos">[</span><span class="pl-c1">6</span><span class="pl-kos">,</span> <span class="pl-c1">10</span><span class="pl-kos">]</span><span class="pl-kos">,</span>                   <span class="pl-c">// BETWEEN 6 AND 10</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">notBetween</span><span class="pl-kos">]</span>: <span class="pl-kos">[</span><span class="pl-c1">11</span><span class="pl-kos">,</span> <span class="pl-c1">15</span><span class="pl-kos">]</span><span class="pl-kos">,</span>               <span class="pl-c">// NOT BETWEEN 11 AND 15</span>

      <span class="pl-c">// 其它操作符</span>

      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">all</span><span class="pl-kos">]</span>: <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">literal</span><span class="pl-kos">(</span><span class="pl-s">'SELECT 1'</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-c">// &gt; ALL (SELECT 1)</span>

      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">in</span><span class="pl-kos">]</span>: <span class="pl-kos">[</span><span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">2</span><span class="pl-kos">]</span><span class="pl-kos">,</span>                         <span class="pl-c">// IN [1, 2]</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">notIn</span><span class="pl-kos">]</span>: <span class="pl-kos">[</span><span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">2</span><span class="pl-kos">]</span><span class="pl-kos">,</span>                      <span class="pl-c">// NOT IN [1, 2]</span>

      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">like</span><span class="pl-kos">]</span>: <span class="pl-s">'%hat'</span><span class="pl-kos">,</span>                       <span class="pl-c">// LIKE '%hat'</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">notLike</span><span class="pl-kos">]</span>: <span class="pl-s">'%hat'</span><span class="pl-kos">,</span>                    <span class="pl-c">// NOT LIKE '%hat'</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">startsWith</span><span class="pl-kos">]</span>: <span class="pl-s">'hat'</span><span class="pl-kos">,</span>                  <span class="pl-c">// LIKE 'hat%'</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">endsWith</span><span class="pl-kos">]</span>: <span class="pl-s">'hat'</span><span class="pl-kos">,</span>                    <span class="pl-c">// LIKE '%hat'</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">substring</span><span class="pl-kos">]</span>: <span class="pl-s">'hat'</span><span class="pl-kos">,</span>                   <span class="pl-c">// LIKE '%hat%'</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">iLike</span><span class="pl-kos">]</span>: <span class="pl-s">'%hat'</span><span class="pl-kos">,</span>                      <span class="pl-c">// ILIKE '%hat' (不区分大小写) (仅 PG)</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">notILike</span><span class="pl-kos">]</span>: <span class="pl-s">'%hat'</span><span class="pl-kos">,</span>                   <span class="pl-c">// NOT ILIKE '%hat'  (仅 PG)</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">regexp</span><span class="pl-kos">]</span>: <span class="pl-s">'^[h|a|t]'</span><span class="pl-kos">,</span>                 <span class="pl-c">// REGEXP/~ '^[h|a|t]' (仅 MySQL/PG)</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">notRegexp</span><span class="pl-kos">]</span>: <span class="pl-s">'^[h|a|t]'</span><span class="pl-kos">,</span>              <span class="pl-c">// NOT REGEXP/!~ '^[h|a|t]' (仅 MySQL/PG)</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">iRegexp</span><span class="pl-kos">]</span>: <span class="pl-s">'^[h|a|t]'</span><span class="pl-kos">,</span>                <span class="pl-c">// ~* '^[h|a|t]' (仅 PG)</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">notIRegexp</span><span class="pl-kos">]</span>: <span class="pl-s">'^[h|a|t]'</span><span class="pl-kos">,</span>             <span class="pl-c">// !~* '^[h|a|t]' (仅 PG)</span>

      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">any</span><span class="pl-kos">]</span>: <span class="pl-kos">[</span><span class="pl-c1">2</span><span class="pl-kos">,</span> <span class="pl-c1">3</span><span class="pl-kos">]</span><span class="pl-kos">,</span>                        <span class="pl-c">// ANY ARRAY[2, 3]::INTEGER (仅 PG)</span>

      <span class="pl-c">// 在 Postgres 中, Op.like/Op.iLike/Op.notLike 可以结合 Op.any 使用:</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">like</span><span class="pl-kos">]</span>: <span class="pl-kos">{</span> <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">any</span><span class="pl-kos">]</span>: <span class="pl-kos">[</span><span class="pl-s">'cat'</span><span class="pl-kos">,</span> <span class="pl-s">'hat'</span><span class="pl-kos">]</span> <span class="pl-kos">}</span>  <span class="pl-c">// LIKE ANY ARRAY['cat', 'hat']</span>

      <span class="pl-c">// 还有更多的仅限 postgres 的范围运算符,请参见下文</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h4><code>Op.in</code>&nbsp;的简写语法</h4>
  <p>直接将数组参数传递给&nbsp;<code>where</code>&nbsp;将隐式使用&nbsp;<code>IN</code>&nbsp;运算符：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">id</span>: <span class="pl-kos">[</span><span class="pl-c1">1</span><span class="pl-kos">,</span><span class="pl-c1">2</span><span class="pl-kos">,</span><span class="pl-c1">3</span><span class="pl-kos">]</span> <span class="pl-c">// 等同使用 `id: { [Op.in]: [1,2,3] }`</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// SELECT ... FROM "posts" AS "post" WHERE "post"."id" IN (1, 2, 3);</span></pre>
  </div>
  <h3>运算符的逻辑组合</h3>
  <p>运算符&nbsp;<code>Op.and</code>,&nbsp;<code>Op.or</code>&nbsp;和&nbsp;<code>Op.not</code>&nbsp;可用于创建任意复杂的嵌套逻辑比较.</p>
  <h4>使用&nbsp;<code>Op.and</code>&nbsp;和&nbsp;<code>Op.or</code>&nbsp;示例</h4>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> Op <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">"sequelize"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">rank</span>: <span class="pl-kos">{</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">or</span><span class="pl-kos">]</span>: <span class="pl-kos">{</span>
        <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">lt</span><span class="pl-kos">]</span>: <span class="pl-c1">1000</span><span class="pl-kos">,</span>
        <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">eq</span><span class="pl-kos">]</span>: <span class="pl-c1">null</span>
      <span class="pl-kos">}</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-c">// rank &lt; 1000 OR rank IS NULL</span>

    <span class="pl-kos">{</span>
      <span class="pl-c1">createdAt</span>: <span class="pl-kos">{</span>
        <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">lt</span><span class="pl-kos">]</span>: <span class="pl-k">new</span> <span class="pl-v">Date</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
        <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">gt</span><span class="pl-kos">]</span>: <span class="pl-k">new</span> <span class="pl-v">Date</span><span class="pl-kos">(</span><span class="pl-k">new</span> <span class="pl-v">Date</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">-</span> <span class="pl-c1">24</span> * <span class="pl-c1">60</span> * <span class="pl-c1">60</span> * <span class="pl-c1">1000</span><span class="pl-kos">)</span>
      <span class="pl-kos">}</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-c">// createdAt &lt; [timestamp] AND createdAt &gt; [timestamp]</span>

    <span class="pl-kos">{</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">or</span><span class="pl-kos">]</span>: <span class="pl-kos">[</span>
        <span class="pl-kos">{</span>
          <span class="pl-c1">title</span>: <span class="pl-kos">{</span>
            <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">like</span><span class="pl-kos">]</span>: <span class="pl-s">'Boat%'</span>
          <span class="pl-kos">}</span>
        <span class="pl-kos">}</span><span class="pl-kos">,</span>
        <span class="pl-kos">{</span>
          <span class="pl-c1">description</span>: <span class="pl-kos">{</span>
            <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">like</span><span class="pl-kos">]</span>: <span class="pl-s">'%boat%'</span>
          <span class="pl-kos">}</span>
        <span class="pl-kos">}</span>
      <span class="pl-kos">]</span>
    <span class="pl-kos">}</span>
    <span class="pl-c">// title LIKE 'Boat%' OR description LIKE '%boat%'</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h4>使用&nbsp;<code>Op.not</code>&nbsp;示例</h4>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">name</span>: <span class="pl-s">'Some Project'</span><span class="pl-kos">,</span>
    <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">not</span><span class="pl-kos">]</span>: <span class="pl-kos">[</span>
      <span class="pl-kos">{</span> <span class="pl-c1">id</span>: <span class="pl-kos">[</span><span class="pl-c1">1</span><span class="pl-kos">,</span><span class="pl-c1">2</span><span class="pl-kos">,</span><span class="pl-c1">3</span><span class="pl-kos">]</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
      <span class="pl-kos">{</span>
        <span class="pl-c1">description</span>: <span class="pl-kos">{</span>
          <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">like</span><span class="pl-kos">]</span>: <span class="pl-s">'Hello%'</span>
        <span class="pl-kos">}</span>
      <span class="pl-kos">}</span>
    <span class="pl-kos">]</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>上面将生成：</p>
  <div class="highlight highlight-source-sql">
<pre><span class="pl-k">SELECT</span> <span class="pl-k">*</span>
<span class="pl-k">FROM</span> <span class="pl-s"><span class="pl-pds">`</span>Projects<span class="pl-pds">`</span></span>
<span class="pl-k">WHERE</span> (
  <span class="pl-s"><span class="pl-pds">`</span>Projects<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>name<span class="pl-pds">`</span></span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">'</span>a project<span class="pl-pds">'</span></span>
  <span class="pl-k">AND</span> NOT (
    <span class="pl-s"><span class="pl-pds">`</span>Projects<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span> <span class="pl-k">IN</span> (<span class="pl-c1">1</span>,<span class="pl-c1">2</span>,<span class="pl-c1">3</span>)
    <span class="pl-k">OR</span>
    <span class="pl-s"><span class="pl-pds">`</span>Projects<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>description<span class="pl-pds">`</span></span> <span class="pl-k">LIKE</span> <span class="pl-s"><span class="pl-pds">'</span>Hello%<span class="pl-pds">'</span></span>
  )
)</pre>
  </div>
  <h3>高级查询(不仅限于列)</h3>
  <p>如果你想得到类似&nbsp;<code>WHERE char_length("content") = 7</code>&nbsp;的结果怎么办？</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">where</span><span class="pl-kos">(</span><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">fn</span><span class="pl-kos">(</span><span class="pl-s">'char_length'</span><span class="pl-kos">,</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">col</span><span class="pl-kos">(</span><span class="pl-s">'content'</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-c1">7</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// SELECT ... FROM "posts" AS "post" WHERE char_length("content") = 7</span></pre>
  </div>
  <p>请注意方法&nbsp;<a href="https://sequelize.org/master/class/lib/sequelize.js~Sequelize.html#static-method-fn" rel="nofollow"><code>sequelize.fn</code></a>&nbsp;和&nbsp;<a href="https://sequelize.org/master/class/lib/sequelize.js~Sequelize.html#static-method-col" rel="nofollow"><code>sequelize.col</code></a>&nbsp;的用法,应分别用于指定 SQL 函数调用和列. 应该使用这些方法,而不是传递纯字符串(例如&nbsp;<code>char_length(content)</code>),因为 Sequelize 需要以不同的方式对待这种情况(例如,使用其他符号转义方法).</p>
  <p>如果你需要更复杂的东西怎么办？</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">or</span><span class="pl-kos">]</span>: <span class="pl-kos">[</span>
      <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">where</span><span class="pl-kos">(</span><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">fn</span><span class="pl-kos">(</span><span class="pl-s">'char_length'</span><span class="pl-kos">,</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">col</span><span class="pl-kos">(</span><span class="pl-s">'content'</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-c1">7</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
      <span class="pl-kos">{</span>
        <span class="pl-c1">content</span>: <span class="pl-kos">{</span>
          <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">like</span><span class="pl-kos">]</span>: <span class="pl-s">'Hello%'</span>
        <span class="pl-kos">}</span>
      <span class="pl-kos">}</span><span class="pl-kos">,</span>
      <span class="pl-kos">{</span>
        <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">and</span><span class="pl-kos">]</span>: <span class="pl-kos">[</span>
          <span class="pl-kos">{</span> <span class="pl-c1">status</span>: <span class="pl-s">'draft'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
          <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">where</span><span class="pl-kos">(</span><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">fn</span><span class="pl-kos">(</span><span class="pl-s">'char_length'</span><span class="pl-kos">,</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">col</span><span class="pl-kos">(</span><span class="pl-s">'content'</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
            <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">gt</span><span class="pl-kos">]</span>: <span class="pl-c1">10</span>
          <span class="pl-kos">}</span><span class="pl-kos">)</span>
        <span class="pl-kos">]</span>
      <span class="pl-kos">}</span>
    <span class="pl-kos">]</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>上面生成了以下SQL：</p>
  <div class="highlight highlight-source-sql">
<pre><span class="pl-k">SELECT</span>
  ...
<span class="pl-k">FROM</span> <span class="pl-s"><span class="pl-pds">"</span>posts<span class="pl-pds">"</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">"</span>post<span class="pl-pds">"</span></span>
<span class="pl-k">WHERE</span> (
  char_length(<span class="pl-s"><span class="pl-pds">"</span>content<span class="pl-pds">"</span></span>) <span class="pl-k">=</span> <span class="pl-c1">7</span>
  <span class="pl-k">OR</span>
  <span class="pl-s"><span class="pl-pds">"</span>post<span class="pl-pds">"</span></span>.<span class="pl-s"><span class="pl-pds">"</span>content<span class="pl-pds">"</span></span> <span class="pl-k">LIKE</span> <span class="pl-s"><span class="pl-pds">'</span>Hello%<span class="pl-pds">'</span></span>
  <span class="pl-k">OR</span> (
    <span class="pl-s"><span class="pl-pds">"</span>post<span class="pl-pds">"</span></span>.<span class="pl-s"><span class="pl-pds">"</span>status<span class="pl-pds">"</span></span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">'</span>draft<span class="pl-pds">'</span></span>
    <span class="pl-k">AND</span>
    char_length(<span class="pl-s"><span class="pl-pds">"</span>content<span class="pl-pds">"</span></span>) <span class="pl-k">&gt;</span> <span class="pl-c1">10</span>
  )
)</pre>
  </div>
  <h3>仅限 Postgres 的范围运算符</h3>
  <p>可以使用所有支持的运算符查询范围类型.</p>
  <p>请记住,提供的范围值也可以<a href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/other-topics/other-data-types.md">定义绑定的 包含/排除</a>.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">contains</span><span class="pl-kos">]</span>: <span class="pl-c1">2</span><span class="pl-kos">,</span>            <span class="pl-c">// @&gt; '2'::integer  (PG range 包含元素运算符)</span>
<span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">contains</span><span class="pl-kos">]</span>: <span class="pl-kos">[</span><span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">2</span><span class="pl-kos">]</span><span class="pl-kos">,</span>       <span class="pl-c">// @&gt; [1, 2)        (PG range 包含范围运算符)</span>
<span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">contained</span><span class="pl-kos">]</span>: <span class="pl-kos">[</span><span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">2</span><span class="pl-kos">]</span><span class="pl-kos">,</span>      <span class="pl-c">// &lt;@ [1, 2)        (PG range 包含于运算符)</span>
<span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">overlap</span><span class="pl-kos">]</span>: <span class="pl-kos">[</span><span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">2</span><span class="pl-kos">]</span><span class="pl-kos">,</span>        <span class="pl-c">// &amp;&amp; [1, 2)        (PG range 重叠(有共同点)运算符)</span>
<span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">adjacent</span><span class="pl-kos">]</span>: <span class="pl-kos">[</span><span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">2</span><span class="pl-kos">]</span><span class="pl-kos">,</span>       <span class="pl-c">// -|- [1, 2)       (PG range 相邻运算符)</span>
<span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">strictLeft</span><span class="pl-kos">]</span>: <span class="pl-kos">[</span><span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">2</span><span class="pl-kos">]</span><span class="pl-kos">,</span>     <span class="pl-c">// &lt;&lt; [1, 2)        (PG range 左严格运算符)</span>
<span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">strictRight</span><span class="pl-kos">]</span>: <span class="pl-kos">[</span><span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">2</span><span class="pl-kos">]</span><span class="pl-kos">,</span>    <span class="pl-c">// &gt;&gt; [1, 2)        (PG range 右严格运算符)</span>
<span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">noExtendRight</span><span class="pl-kos">]</span>: <span class="pl-kos">[</span><span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">2</span><span class="pl-kos">]</span><span class="pl-kos">,</span>  <span class="pl-c">// &amp;&lt; [1, 2)        (PG range 未延伸到右侧运算符)</span>
<span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">noExtendLeft</span><span class="pl-kos">]</span>: <span class="pl-kos">[</span><span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">2</span><span class="pl-kos">]</span><span class="pl-kos">,</span>   <span class="pl-c">// &amp;&gt; [1, 2)        (PG range 未延伸到左侧运算符)</span></pre>
  </div>
  <h3>不推荐使用: 操作符别名</h3>
  <p>在 Sequelize v4 中,可以指定字符串来引用运算符,而不是使用 Symbols. 现在不建议使用此方法,很可能在下一个主要版本中将其删除. 如果确实需要,可以在 Sequelize 构造函数中传递&nbsp;<code>operatorAliases</code>&nbsp;参数.</p>
  <p>例如:</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> Sequelize<span class="pl-kos">,</span> Op <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">"sequelize"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-s">'sqlite::memory:'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">operatorsAliases</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">$gt</span>: <span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">gt</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 现在我们可以在 where 子句中使用 `$gt` 代替 `[Op.gt]`：</span>
<span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">$gt</span>: <span class="pl-c1">6</span> <span class="pl-c">// 就像使用 [Op.gt]</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h2>简单 UPDATE 查询</h2>
  <p>Update 查询也接受&nbsp;<code>where</code>&nbsp;参数,就像上面的读取查询一样.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 将所有没有姓氏的人更改为 "Doe"</span>
<span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">update</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">lastName</span>: <span class="pl-s">"Doe"</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">lastName</span>: <span class="pl-c1">null</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h2>简单 DELETE 查询</h2>
  <p>Delete 查询也接受&nbsp;<code>where</code>&nbsp;参数,就像上面的读取查询一样.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 删除所有名为 "Jane" 的人 </span>
<span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">destroy</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">firstName</span>: <span class="pl-s">"Jane"</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>要销毁所有内容,可以使用&nbsp;<code>TRUNCATE</code>&nbsp;SQL：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 截断表格</span>
<span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">destroy</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">truncate</span>: <span class="pl-c1">true</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h2>批量创建</h2>
  <p>Sequelize 提供了&nbsp;<code>Model.bulkCreate</code>&nbsp;方法,以允许仅一次查询即可一次创建多个记录.</p>
  <p>通过接收数组对象而不是单个对象,<code>Model.bulkCreate</code>&nbsp;的用法与&nbsp;<code>Model.create</code>&nbsp;非常相似.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">captains</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Captain</span><span class="pl-kos">.</span><span class="pl-en">bulkCreate</span><span class="pl-kos">(</span><span class="pl-kos">[</span>
  <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'Jack Sparrow'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'Davy Jones'</span> <span class="pl-kos">}</span>
<span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">captains</span><span class="pl-kos">.</span><span class="pl-c1">length</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 2</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">captains</span><span class="pl-kos">[</span><span class="pl-c1">0</span><span class="pl-kos">]</span> <span class="pl-k">instanceof</span> <span class="pl-v">Captain</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// true</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">captains</span><span class="pl-kos">[</span><span class="pl-c1">0</span><span class="pl-kos">]</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 'Jack Sparrow'</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">captains</span><span class="pl-kos">[</span><span class="pl-c1">0</span><span class="pl-kos">]</span><span class="pl-kos">.</span><span class="pl-c1">id</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 1 // (或另一个自动生成的值)</span></pre>
  </div>
  <p>但是,默认情况下,<code>bulkCreate</code>&nbsp;不会在要创建的每个对象上运行验证(而&nbsp;<code>create</code>&nbsp;可以做到). 为了使&nbsp;<code>bulkCreate</code>&nbsp;也运行这些验证,必须通过<code>validate: true</code>&nbsp;参数. 但这会降低性能. 用法示例：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">Foo</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'foo'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">bar</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">TEXT</span><span class="pl-kos">,</span>
    <span class="pl-c1">validate</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">len</span>: <span class="pl-kos">[</span><span class="pl-c1">4</span><span class="pl-kos">,</span> <span class="pl-c1">6</span><span class="pl-kos">]</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 这不会引发错误,两个实例都将被创建</span>
<span class="pl-k">await</span> <span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">bulkCreate</span><span class="pl-kos">(</span><span class="pl-kos">[</span>
  <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'abc123'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'name too long'</span> <span class="pl-kos">}</span>
<span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 这将引发错误,不会创建任何内容</span>
<span class="pl-k">await</span> <span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">bulkCreate</span><span class="pl-kos">(</span><span class="pl-kos">[</span>
  <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'abc123'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'name too long'</span> <span class="pl-kos">}</span>
<span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">validate</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>如果你直接从用户获取值,那么限制实际插入的列可能会有所帮助. 为了做到这一点,<code>bulkCreate()</code>&nbsp;接受一个&nbsp;<code>fields</code>&nbsp;参数,该参数须为你要定义字段的数组(其余字段将被忽略).</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">bulkCreate</span><span class="pl-kos">(</span><span class="pl-kos">[</span>
  <span class="pl-kos">{</span> <span class="pl-c1">username</span>: <span class="pl-s">'foo'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-kos">{</span> <span class="pl-c1">username</span>: <span class="pl-s">'bar'</span><span class="pl-kos">,</span> <span class="pl-c1">admin</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span>
<span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">fields</span>: <span class="pl-kos">[</span><span class="pl-s">'username'</span><span class="pl-kos">]</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// foo 和 bar 都不会是管理员.</span></pre>
  </div>
  <h2>排序和分组</h2>
  <p>Sequelize 提供了&nbsp;<code>order</code>&nbsp;and&nbsp;<code>group</code>&nbsp;参数,来与&nbsp;<code>ORDER BY</code>&nbsp;和&nbsp;<code>GROUP BY</code>&nbsp;一起使用.</p>
  <h3>排序</h3>
  <p><code>order</code>&nbsp;参数采用一系列&nbsp;<em>项</em>&nbsp;来让 sequelize 方法对查询进行排序. 这些&nbsp;<em>项</em>&nbsp;本身是&nbsp;<code>[column, direction]</code>&nbsp;形式的数组. 该列将被正确转义,并且将在有效方向列表中进行验证(例如&nbsp;<code>ASC</code>,&nbsp;<code>DESC</code>,&nbsp;<code>NULLS FIRST</code>&nbsp;等).</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Subtask</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">order</span>: <span class="pl-kos">[</span>
    <span class="pl-c">// 将转义 title 并针对有效方向列表进行降序排列</span>
    <span class="pl-kos">[</span><span class="pl-s">'title'</span><span class="pl-kos">,</span> <span class="pl-s">'DESC'</span><span class="pl-kos">]</span><span class="pl-kos">,</span>

    <span class="pl-c">// 将按最大年龄进行升序排序</span>
    <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">fn</span><span class="pl-kos">(</span><span class="pl-s">'max'</span><span class="pl-kos">,</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">col</span><span class="pl-kos">(</span><span class="pl-s">'age'</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">,</span>

    <span class="pl-c">// 将按最大年龄进行降序排序</span>
    <span class="pl-kos">[</span><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">fn</span><span class="pl-kos">(</span><span class="pl-s">'max'</span><span class="pl-kos">,</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">col</span><span class="pl-kos">(</span><span class="pl-s">'age'</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">'DESC'</span><span class="pl-kos">]</span><span class="pl-kos">,</span>

    <span class="pl-c">// 将按 otherfunction(`col1`, 12, 'lalala') 进行降序排序</span>
    <span class="pl-kos">[</span><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">fn</span><span class="pl-kos">(</span><span class="pl-s">'otherfunction'</span><span class="pl-kos">,</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">col</span><span class="pl-kos">(</span><span class="pl-s">'col1'</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-c1">12</span><span class="pl-kos">,</span> <span class="pl-s">'lalala'</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">'DESC'</span><span class="pl-kos">]</span><span class="pl-kos">,</span>

    <span class="pl-c">// 将使用模型名称作为关联名称按关联模型的 createdAt 排序.</span>
    <span class="pl-kos">[</span><span class="pl-v">Task</span><span class="pl-kos">,</span> <span class="pl-s">'createdAt'</span><span class="pl-kos">,</span> <span class="pl-s">'DESC'</span><span class="pl-kos">]</span><span class="pl-kos">,</span>

    <span class="pl-c">// 将使用模型名称作为关联名称通过关联模型的 createdAt 排序.</span>
    <span class="pl-kos">[</span><span class="pl-v">Task</span><span class="pl-kos">,</span> <span class="pl-v">Project</span><span class="pl-kos">,</span> <span class="pl-s">'createdAt'</span><span class="pl-kos">,</span> <span class="pl-s">'DESC'</span><span class="pl-kos">]</span><span class="pl-kos">,</span>

    <span class="pl-c">// 将使用关联名称按关联模型的 createdAt 排序.</span>
    <span class="pl-kos">[</span><span class="pl-s">'Task'</span><span class="pl-kos">,</span> <span class="pl-s">'createdAt'</span><span class="pl-kos">,</span> <span class="pl-s">'DESC'</span><span class="pl-kos">]</span><span class="pl-kos">,</span>

    <span class="pl-c">// 将使用关联的名称按嵌套的关联模型的 createdAt 排序.</span>
    <span class="pl-kos">[</span><span class="pl-s">'Task'</span><span class="pl-kos">,</span> <span class="pl-s">'Project'</span><span class="pl-kos">,</span> <span class="pl-s">'createdAt'</span><span class="pl-kos">,</span> <span class="pl-s">'DESC'</span><span class="pl-kos">]</span><span class="pl-kos">,</span>

    <span class="pl-c">// 将使用关联对象按关联模型的 createdAt 排序. (首选方法)</span>
    <span class="pl-kos">[</span><span class="pl-v">Subtask</span><span class="pl-kos">.</span><span class="pl-c1">associations</span><span class="pl-kos">.</span><span class="pl-c1">Task</span><span class="pl-kos">,</span> <span class="pl-s">'createdAt'</span><span class="pl-kos">,</span> <span class="pl-s">'DESC'</span><span class="pl-kos">]</span><span class="pl-kos">,</span>

    <span class="pl-c">// 将使用关联对象按嵌套关联模型的 createdAt 排序. (首选方法)</span>
    <span class="pl-kos">[</span><span class="pl-v">Subtask</span><span class="pl-kos">.</span><span class="pl-c1">associations</span><span class="pl-kos">.</span><span class="pl-c1">Task</span><span class="pl-kos">,</span> <span class="pl-v">Task</span><span class="pl-kos">.</span><span class="pl-c1">associations</span><span class="pl-kos">.</span><span class="pl-c1">Project</span><span class="pl-kos">,</span> <span class="pl-s">'createdAt'</span><span class="pl-kos">,</span> <span class="pl-s">'DESC'</span><span class="pl-kos">]</span><span class="pl-kos">,</span>

    <span class="pl-c">// 将使用简单的关联对象按关联模型的 createdAt 排序.</span>
    <span class="pl-kos">[</span><span class="pl-kos">{</span><span class="pl-c1">model</span>: <span class="pl-v">Task</span><span class="pl-kos">,</span> <span class="pl-c1">as</span>: <span class="pl-s">'Task'</span><span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-s">'createdAt'</span><span class="pl-kos">,</span> <span class="pl-s">'DESC'</span><span class="pl-kos">]</span><span class="pl-kos">,</span>

    <span class="pl-c">// 将由嵌套关联模型的 createdAt 简单关联对象排序.</span>
    <span class="pl-kos">[</span><span class="pl-kos">{</span><span class="pl-c1">model</span>: <span class="pl-v">Task</span><span class="pl-kos">,</span> <span class="pl-c1">as</span>: <span class="pl-s">'Task'</span><span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span><span class="pl-c1">model</span>: <span class="pl-v">Project</span><span class="pl-kos">,</span> <span class="pl-c1">as</span>: <span class="pl-s">'Project'</span><span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-s">'createdAt'</span><span class="pl-kos">,</span> <span class="pl-s">'DESC'</span><span class="pl-kos">]</span>
  <span class="pl-kos">]</span><span class="pl-kos">,</span>

  <span class="pl-c">// 将按最大年龄降序排列</span>
  <span class="pl-c1">order</span>: <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">literal</span><span class="pl-kos">(</span><span class="pl-s">'max(age) DESC'</span><span class="pl-kos">)</span><span class="pl-kos">,</span>

  <span class="pl-c">// 如果忽略方向,则默认升序,将按最大年龄升序排序</span>
  <span class="pl-c1">order</span>: <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">fn</span><span class="pl-kos">(</span><span class="pl-s">'max'</span><span class="pl-kos">,</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">col</span><span class="pl-kos">(</span><span class="pl-s">'age'</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">,</span>

  <span class="pl-c">// 如果省略方向,则默认升序, 将按年龄升序排列</span>
  <span class="pl-c1">order</span>: <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">col</span><span class="pl-kos">(</span><span class="pl-s">'age'</span><span class="pl-kos">)</span><span class="pl-kos">,</span>

  <span class="pl-c">// 将根据方言随机排序(但不是 fn('RAND') 或 fn('RANDOM'))</span>
  <span class="pl-c1">order</span>: <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">random</span><span class="pl-kos">(</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">order</span>: <span class="pl-kos">[</span>
    <span class="pl-c">// 将返回 `name`</span>
    <span class="pl-kos">[</span><span class="pl-s">'name'</span><span class="pl-kos">]</span><span class="pl-kos">,</span>
    <span class="pl-c">// 将返回 `username` DESC</span>
    <span class="pl-kos">[</span><span class="pl-s">'username'</span><span class="pl-kos">,</span> <span class="pl-s">'DESC'</span><span class="pl-kos">]</span><span class="pl-kos">,</span>
    <span class="pl-c">// 将返回 max(`age`)</span>
    <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">fn</span><span class="pl-kos">(</span><span class="pl-s">'max'</span><span class="pl-kos">,</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">col</span><span class="pl-kos">(</span><span class="pl-s">'age'</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
    <span class="pl-c">// 将返回 max(`age`) DESC</span>
    <span class="pl-kos">[</span><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">fn</span><span class="pl-kos">(</span><span class="pl-s">'max'</span><span class="pl-kos">,</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">col</span><span class="pl-kos">(</span><span class="pl-s">'age'</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">'DESC'</span><span class="pl-kos">]</span><span class="pl-kos">,</span>
    <span class="pl-c">// 将返回 otherfunction(`col1`, 12, 'lalala') DESC</span>
    <span class="pl-kos">[</span><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">fn</span><span class="pl-kos">(</span><span class="pl-s">'otherfunction'</span><span class="pl-kos">,</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">col</span><span class="pl-kos">(</span><span class="pl-s">'col1'</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-c1">12</span><span class="pl-kos">,</span> <span class="pl-s">'lalala'</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">'DESC'</span><span class="pl-kos">]</span><span class="pl-kos">,</span>
    <span class="pl-c">// 将返回 otherfunction(awesomefunction(`col`)) DESC, 这种嵌套可能是无限的!</span>
    <span class="pl-kos">[</span><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">fn</span><span class="pl-kos">(</span><span class="pl-s">'otherfunction'</span><span class="pl-kos">,</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">fn</span><span class="pl-kos">(</span><span class="pl-s">'awesomefunction'</span><span class="pl-kos">,</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">col</span><span class="pl-kos">(</span><span class="pl-s">'col'</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">'DESC'</span><span class="pl-kos">]</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>回顾一下,order 数组的元素可以如下：</p>
  <ul>
    <li>一个字符串 (它将被自动引用)</li>
    <li>一个数组, 其第一个元素将被引用,第二个将被逐字追加</li>
    <li>一个具有&nbsp;<code>raw</code>&nbsp;字段的对象:
      <ul>
        <li><code>raw</code>&nbsp;内容将不加引用地逐字添加</li>
        <li>其他所有内容都将被忽略,如果未设置&nbsp;<code>raw</code>,查询将失败</li>
      </ul>
    </li>
    <li>调用&nbsp;<code>Sequelize.fn</code>&nbsp;(这将在 SQL 中生成一个函数调用)</li>
    <li>调用&nbsp;<code>Sequelize.col</code>&nbsp;(这将引用列名)</li>
  </ul>
  <h3>分组</h3>
  <p>分组和排序的语法相同,只是分组不接受方向作为数组的最后一个参数(不存在&nbsp;<code>ASC</code>,&nbsp;<code>DESC</code>,&nbsp;<code>NULLS FIRST</code>&nbsp;等).</p>
  <p>你还可以将字符串直接传递给&nbsp;<code>group</code>,该字符串将直接(普通)包含在生成的 SQL 中. 请谨慎使用,请勿与用户生成的内容一起使用.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">group</span>: <span class="pl-s">'name'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 生成 'GROUP BY name'</span></pre>
  </div>
  <h2>限制和分页</h2>
  <p>使用&nbsp;<code>limit</code>&nbsp;和&nbsp;<code>offset</code>&nbsp;参数可以进行 限制/分页：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 提取10个实例/行</span>
<span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">limit</span>: <span class="pl-c1">10</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 跳过8个实例/行</span>
<span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">offset</span>: <span class="pl-c1">8</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 跳过5个实例,然后获取5个实例</span>
<span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">offset</span>: <span class="pl-c1">5</span><span class="pl-kos">,</span> <span class="pl-c1">limit</span>: <span class="pl-c1">5</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>通常这些与&nbsp;<code>order</code>&nbsp;参数一起使用.</p>
  <h2>实用方法</h2>
  <p>Sequelize 还提供了一些实用方法.</p>
  <h3><code>count</code></h3>
  <p><code>count</code>&nbsp;方法仅计算数据库中元素出现的次数.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">`这有 <span class="pl-s1"><span class="pl-kos">${</span><span class="pl-k">await</span> <span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">count</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">}</span></span> 个项目`</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">const</span> <span class="pl-s1">amount</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">count</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">id</span>: <span class="pl-kos">{</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">gt</span><span class="pl-kos">]</span>: <span class="pl-c1">25</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">`这有 <span class="pl-s1"><span class="pl-kos">${</span>amount<span class="pl-kos">}</span></span> 个项目 id 大于 25`</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h3><code>max</code>,&nbsp;<code>min</code>&nbsp;和&nbsp;<code>sum</code></h3>
  <p>Sequelize 还提供了 max,min 和 sum 便捷方法.</p>
  <p>假设我们有三个用户,分别是10、5和40岁.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">max</span><span class="pl-kos">(</span><span class="pl-s">'age'</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 40</span>
<span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">max</span><span class="pl-kos">(</span><span class="pl-s">'age'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">where</span>: <span class="pl-kos">{</span> <span class="pl-c1">age</span>: <span class="pl-kos">{</span> <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">lt</span><span class="pl-kos">]</span>: <span class="pl-c1">20</span> <span class="pl-kos">}</span> <span class="pl-kos">}</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 10</span>
<span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">min</span><span class="pl-kos">(</span><span class="pl-s">'age'</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 5</span>
<span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">min</span><span class="pl-kos">(</span><span class="pl-s">'age'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">where</span>: <span class="pl-kos">{</span> <span class="pl-c1">age</span>: <span class="pl-kos">{</span> <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">gt</span><span class="pl-kos">]</span>: <span class="pl-c1">5</span> <span class="pl-kos">}</span> <span class="pl-kos">}</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 10</span>
<span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">sum</span><span class="pl-kos">(</span><span class="pl-s">'age'</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 55</span>
<span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">sum</span><span class="pl-kos">(</span><span class="pl-s">'age'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">where</span>: <span class="pl-kos">{</span> <span class="pl-c1">age</span>: <span class="pl-kos">{</span> <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">gt</span><span class="pl-kos">]</span>: <span class="pl-c1">5</span> <span class="pl-kos">}</span> <span class="pl-kos">}</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 50</span></pre>
  </div>
  <pre><span class="pl-c">&nbsp;</span></pre>
  <h1>Model Querying - Finders - 模型查询(查找器)</h1>
  <p>Finder 方法是生成&nbsp;<code>SELECT</code>&nbsp;查询的方法.</p>
  <p>默认情况下,所有 finder 方法的结果都是模型类的实例(与普通的 JavaScript 对象相反). 这意味着在数据库返回结果之后,Sequelize 会自动将所有内容包装在适当的实例对象中. 在少数情况下,当结果太多时,这种包装可能会效率低下. 要禁用此包装并收到简单的响应,请将&nbsp;<code>{ raw: true }</code>&nbsp;作为参数传递给 finder 方法.</p>
  <h2><code>findAll</code></h2>
  <p>在上一教程中已经知道&nbsp;<code>findAll</code>&nbsp;方法. 它生成一个标准的&nbsp;<code>SELECT</code>&nbsp;查询,该查询将从表中检索所有条目(除非受到&nbsp;<code>where</code>&nbsp;子句的限制).</p>
  <h2><code>findByPk</code></h2>
  <p><code>findByPk</code>&nbsp;方法使用提供的主键从表中仅获得一个条目.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">project</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">findByPk</span><span class="pl-kos">(</span><span class="pl-c1">123</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">project</span> <span class="pl-c1">===</span> <span class="pl-c1">null</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">'Not found!'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-kos">{</span>
  <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">project</span> <span class="pl-k">instanceof</span> <span class="pl-v">Project</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// true</span>
  <span class="pl-c">// 它的主键是 123</span>
<span class="pl-kos">}</span></pre>
  </div>
  <h2><code>findOne</code></h2>
  <p><code>findOne</code>&nbsp;方法获得它找到的第一个条目(它可以满足提供的可选查询参数).</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">project</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">where</span>: <span class="pl-kos">{</span> <span class="pl-c1">title</span>: <span class="pl-s">'My Title'</span> <span class="pl-kos">}</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">project</span> <span class="pl-c1">===</span> <span class="pl-c1">null</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">'Not found!'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-kos">{</span>
  <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">project</span> <span class="pl-k">instanceof</span> <span class="pl-v">Project</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// true</span>
  <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">project</span><span class="pl-kos">.</span><span class="pl-c1">title</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 'My Title'</span>
<span class="pl-kos">}</span></pre>
  </div>
  <h2><code>findOrCreate</code></h2>
  <p>除非找到一个满足查询参数的结果,否则方法&nbsp;<code>findOrCreate</code>&nbsp;将在表中创建一个条目. 在这两种情况下,它将返回一个实例(找到的实例或创建的实例)和一个布尔值,指示该实例是已创建还是已经存在.</p>
  <p>使用&nbsp;<code>where</code>&nbsp;参数来查找条目,而使用&nbsp;<code>defaults</code>&nbsp;参数来定义必须创建的内容. 如果&nbsp;<code>defaults</code>&nbsp;不包含每一列的值,则 Sequelize 将采用&nbsp;<code>where</code>&nbsp;的值(如果存在).</p>
  <p>假设我们有一个空的数据库,该数据库具有一个&nbsp;<code>User</code>&nbsp;模型,该模型具有一个&nbsp;<code>username</code>&nbsp;和一个&nbsp;<code>job</code>.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">[</span><span class="pl-s1">user</span><span class="pl-kos">,</span> <span class="pl-s1">created</span><span class="pl-kos">]</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findOrCreate</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span> <span class="pl-c1">username</span>: <span class="pl-s">'sdepold'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">defaults</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">job</span>: <span class="pl-s">'Technical Lead JavaScript'</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-c1">username</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 'sdepold'</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-c1">job</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 这可能是也可能不是 'Technical Lead JavaScript'</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">created</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 指示此实例是否刚刚创建的布尔值</span>
<span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">created</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-c1">job</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 这里肯定是 'Technical Lead JavaScript'</span>
<span class="pl-kos">}</span></pre>
  </div>
  <h2><code>findAndCountAll</code></h2>
  <p><code>findAndCountAll</code>&nbsp;方法是结合了&nbsp;<code>findAll</code>&nbsp;和&nbsp;<code>count</code>&nbsp;的便捷方法. 在处理与分页有关的查询时非常有用,在分页中,你想检索带有&nbsp;<code>limit</code>&nbsp;和&nbsp;<code>offset</code>&nbsp;的数据,但又需要知道与查询匹配的记录总数.</p>
  <p><code>findAndCountAll</code>&nbsp;方法返回一个具有两个属性的对象：</p>
  <ul>
    <li><code>count</code>&nbsp;- 一个整数 - 符合查询条件的记录总数</li>
    <li><code>rows</code>&nbsp;- 一个数组对象 - 获得的记录</li>
  </ul>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> count<span class="pl-kos">,</span> rows <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">findAndCountAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">title</span>: <span class="pl-kos">{</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">like</span><span class="pl-kos">]</span>: <span class="pl-s">'foo%'</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">offset</span>: <span class="pl-c1">10</span><span class="pl-kos">,</span>
  <span class="pl-c1">limit</span>: <span class="pl-c1">2</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">count</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">rows</span><span class="pl-kos">)</span><span class="pl-kos">;<br /><br /></span></pre>
    <h1>Getters, Setters &amp; Virtuals - 获取器, 设置器 &amp; 虚拟字段</h1>
    <p>Sequelize 允许你为模型的属性定义自定义获取器和设置器.</p>
    <p>Sequelize 还允许你指定所谓的&nbsp;<em>虚拟属性</em>,它们是 Sequelize 模型上的属性,这些属性在基础 SQL 表中实际上并不存在,而是由 Sequelize 自动填充.它们对于简化代码非常有用.</p>
    <h2>获取器</h2>
    <p>获取器是为模型定义中的一列定义的&nbsp;<code>get()</code>&nbsp;函数：</p>
    <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">User</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'user'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c">// 假设我们想要以大写形式查看每个用户名,</span>
  <span class="pl-c">// 即使它们在数据库本身中不一定是大写的</span>
  <span class="pl-c1">username</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
    <span class="pl-en">get</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-k">const</span> <span class="pl-s1">rawValue</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">getDataValue</span><span class="pl-kos">(</span><span class="pl-s1">username</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
      <span class="pl-k">return</span> <span class="pl-s1">rawValue</span> ? <span class="pl-s1">rawValue</span><span class="pl-kos">.</span><span class="pl-en">toUpperCase</span><span class="pl-kos">(</span><span class="pl-kos">)</span> : <span class="pl-c1">null</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
    </div>
    <p>就像标准 JavaScript 获取器一样,在读取字段值时会自动调用此获取器：</p>
    <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">user</span> <span class="pl-c1">=</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">build</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">username</span>: <span class="pl-s">'SuperUser123'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-c1">username</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 'SUPERUSER123'</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-en">getDataValue</span><span class="pl-kos">(</span><span class="pl-s1">username</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 'SuperUser123'</span></pre>
    </div>
    <p>注意,尽管上面记录为&nbsp;<code>SUPERUSER123</code>,但是真正存储在数据库中的值仍然是&nbsp;<code>SuperUser123</code>. 我们使用了&nbsp;<code>this.getDataValue(username)</code>&nbsp;来获得该值,并将其转换为大写.</p>
    <p>如果我们尝试在获取器中使用&nbsp;<code>this.username</code>,我们将陷入无限循环！ 这就是为什么 Sequelize 提供&nbsp;<code>getDataValue</code>&nbsp;方法的原因.</p>
    <h2>设置器</h2>
    <p>设置器是为模型定义中的一列定义的&nbsp;<code>set()</code>&nbsp;函数. 它接收要设置的值：</p>
    <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">User</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'user'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">username</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">password</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
    <span class="pl-en">set</span><span class="pl-kos">(</span><span class="pl-s1">value</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-c">// 在数据库中以明文形式存储密码是很糟糕的.</span>
      <span class="pl-c">// 使用适当的哈希函数来加密哈希值更好.</span>
      <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">setDataValue</span><span class="pl-kos">(</span><span class="pl-s">'password'</span><span class="pl-kos">,</span> <span class="pl-en">hash</span><span class="pl-kos">(</span><span class="pl-s1">value</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
    </div>
    <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">user</span> <span class="pl-c1">=</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">build</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">username</span>: <span class="pl-s">'someone'</span><span class="pl-kos">,</span> <span class="pl-c1">password</span>: <span class="pl-s">'NotSo&sect;tr0ngP4$SW0RD!'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-c1">password</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// '7cfc84b8ea898bb72462e78b4643cfccd77e9f05678ec2ce78754147ba947acc'</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-en">getDataValue</span><span class="pl-kos">(</span><span class="pl-s1">password</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// '7cfc84b8ea898bb72462e78b4643cfccd77e9f05678ec2ce78754147ba947acc'</span></pre>
    </div>
    <p>Sequelize 在将数据发送到数据库之前自动调用了设置器. 数据库得到的唯一数据是已经散列过的值.</p>
    <p>如果我们想将模型实例中的另一个字段包含在计算中,那也是可以的,而且非常容易！</p>
    <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">User</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'user'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">username</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">password</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
    <span class="pl-en">set</span><span class="pl-kos">(</span><span class="pl-s1">value</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-c">// 在数据库中以明文形式存储密码是很糟糕的.</span>
      <span class="pl-c">// 使用适当的哈希函数来加密哈希值更好.</span>
      <span class="pl-c">// 使用用户名作为盐更好.</span>
      <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">setDataValue</span><span class="pl-kos">(</span><span class="pl-s">'password'</span><span class="pl-kos">,</span> <span class="pl-en">hash</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">username</span> <span class="pl-c1">+</span> <span class="pl-s1">value</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
    </div>
    <p><strong>注意：</strong>&nbsp;上面涉及密码处理的示例尽管比单纯以明文形式存储密码要好得多,但远非完美的安全性. 正确处理密码很困难,这里的所有内容只是为了举例说明 Sequelize 功能. 我们建议让网络安全专家阅读&nbsp;<a href="https://www.owasp.org/" rel="nofollow">OWASP</a>&nbsp;文档或者访问&nbsp;<a href="https://security.stackexchange.com/" rel="nofollow">InfoSec StackExchange</a>.</p>
    <h2>组合获取器和设置器</h2>
    <p>获取器和设置器都可以在同一字段中定义.</p>
    <p>举个例子,假设我们正在建一个&nbsp;<code>Post</code>&nbsp;模型,其&nbsp;<code>content</code>&nbsp;是无限长度的文本. 假设要提高内存使用率,我们要存储内容的压缩版本.</p>
    <p><em>注意：在这种情况下,现代数据库应会自动进行一些压缩. 这只是为了举例.</em></p>
    <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> gzipSync<span class="pl-kos">,</span> gunzipSync <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'zlib'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">const</span> <span class="pl-v">Post</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'post'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">content</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">TEXT</span><span class="pl-kos">,</span>
    <span class="pl-en">get</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-k">const</span> <span class="pl-s1">storedValue</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">getDataValue</span><span class="pl-kos">(</span><span class="pl-s">'content'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
      <span class="pl-k">const</span> <span class="pl-s1">gzippedBuffer</span> <span class="pl-c1">=</span> <span class="pl-v">Buffer</span><span class="pl-kos">.</span><span class="pl-en">from</span><span class="pl-kos">(</span><span class="pl-s1">storedValue</span><span class="pl-kos">,</span> <span class="pl-s">'base64'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
      <span class="pl-k">const</span> <span class="pl-s1">unzippedBuffer</span> <span class="pl-c1">=</span> <span class="pl-en">gunzipSync</span><span class="pl-kos">(</span><span class="pl-s1">gzippedBuffer</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
      <span class="pl-k">return</span> <span class="pl-s1">unzippedBuffer</span><span class="pl-kos">.</span><span class="pl-en">toString</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-en">set</span><span class="pl-kos">(</span><span class="pl-s1">value</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-k">const</span> <span class="pl-s1">gzippedBuffer</span> <span class="pl-c1">=</span> <span class="pl-en">gzipSync</span><span class="pl-kos">(</span><span class="pl-s1">value</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
      <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">setDataValue</span><span class="pl-kos">(</span><span class="pl-s">'content'</span><span class="pl-kos">,</span> <span class="pl-s1">gzippedBuffer</span><span class="pl-kos">.</span><span class="pl-en">toString</span><span class="pl-kos">(</span><span class="pl-s">'base64'</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
    </div>
    <p>通过上述设置,每当我们尝试与&nbsp;<code>Post</code>&nbsp;模型的&nbsp;<code>content</code>&nbsp;字段进行交互时,Sequelize 都会自动处理自定义的获取器和设置器. 例如：</p>
    <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">post</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">content</span>: <span class="pl-s">'Hello everyone!'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">post</span><span class="pl-kos">.</span><span class="pl-c1">content</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 'Hello everyone!'</span>
<span class="pl-c">// 一切都在幕后进行,所以我们甚至都可以忘记内容实际上是</span>
<span class="pl-c">// 作为 gzip 压缩的 base64 字符串存储的！</span>

<span class="pl-c">// 但是,如果我们真的很好奇,我们可以获取 'raw' 数据...</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">post</span><span class="pl-kos">.</span><span class="pl-en">getDataValue</span><span class="pl-kos">(</span><span class="pl-s">'content'</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// Output: 'H4sIAAAAAAAACvNIzcnJV0gtSy2qzM9LVQQAUuk9jQ8AAAA='</span></pre>
    </div>
    <h2>虚拟字段</h2>
    <p>虚拟字段是 Sequelize 在后台填充的字段,但实际上它们不存在于数据库中.</p>
    <p>例如,假设我们有一个 User 的&nbsp;<code>firstName</code>&nbsp;和&nbsp;<code>lastName</code>&nbsp;属性.\</p>
    <p><em>同样,这<a href="https://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/" rel="nofollow">仅是为了示例</a>.</em></p>
    <p>如果有一种简单的方法能直接获取&nbsp;<em>全名</em>&nbsp;那会非常好！ 我们可以将&nbsp;<code>getters</code>&nbsp;的概念与 Sequelize 针对这种情况提供的特殊数据类型结合使用：<code>DataTypes.VIRTUAL</code>:</p>
    <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> DataTypes <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">"sequelize"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">const</span> <span class="pl-v">User</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'user'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">firstName</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">TEXT</span><span class="pl-kos">,</span>
  <span class="pl-c1">lastName</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">TEXT</span><span class="pl-kos">,</span>
  <span class="pl-c1">fullName</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">VIRTUAL</span><span class="pl-kos">,</span>
    <span class="pl-en">get</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-k">return</span> <span class="pl-s">`<span class="pl-s1"><span class="pl-kos">${</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">firstName</span><span class="pl-kos">}</span></span> <span class="pl-s1"><span class="pl-kos">${</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">lastName</span><span class="pl-kos">}</span></span>`</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-en">set</span><span class="pl-kos">(</span><span class="pl-s1">value</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-v">Error</span><span class="pl-kos">(</span><span class="pl-s">'不要尝试设置 `fullName` 的值!'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
    </div>
    <p><code>VIRTUAL</code>&nbsp;字段不会导致数据表也存在此列. 换句话说,上面的模型虽然没有&nbsp;<code>fullName</code>&nbsp;列. 但是它似乎存在着！</p>
    <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">user</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">firstName</span>: <span class="pl-s">'John'</span><span class="pl-kos">,</span> <span class="pl-c1">lastName</span>: <span class="pl-s">'Doe'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-c1">fullName</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 'John Doe'</span></pre>
    </div>
    <h2><code>getterMethods</code>&nbsp;和&nbsp;<code>setterMethods</code></h2>
    <p>Sequelize 在模型定义中还提供了&nbsp;<code>getterMethods</code>&nbsp;和&nbsp;<code>setterMethods</code>&nbsp;参数,以指定看起来像但与虚拟属性不完全相同的事物. 不鼓励使用此方法,并且将来可能会不建议使用(建议直接使用虚拟属性).</p>
    <p>示例:</p>
    <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> Sequelize<span class="pl-kos">,</span> DataTypes <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'sequelize'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-s">'sqlite::memory:'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">const</span> <span class="pl-v">User</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'user'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">firstName</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">lastName</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">getterMethods</span>: <span class="pl-kos">{</span>
    <span class="pl-en">fullName</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-k">return</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">firstName</span> <span class="pl-c1">+</span> <span class="pl-s">' '</span> <span class="pl-c1">+</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">lastName</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">setterMethods</span>: <span class="pl-kos">{</span>
    <span class="pl-en">fullName</span><span class="pl-kos">(</span><span class="pl-s1">value</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-c">// 注意：这仅用于演示.</span>
      <span class="pl-c">// 查阅: https://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/</span>
      <span class="pl-k">const</span> <span class="pl-s1">names</span> <span class="pl-c1">=</span> <span class="pl-s1">value</span><span class="pl-kos">.</span><span class="pl-en">split</span><span class="pl-kos">(</span><span class="pl-s">' '</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
      <span class="pl-k">const</span> <span class="pl-s1">firstName</span> <span class="pl-c1">=</span> <span class="pl-s1">names</span><span class="pl-kos">[</span><span class="pl-c1">0</span><span class="pl-kos">]</span><span class="pl-kos">;</span>
      <span class="pl-k">const</span> <span class="pl-s1">lastName</span> <span class="pl-c1">=</span> <span class="pl-s1">names</span><span class="pl-kos">.</span><span class="pl-en">slice</span><span class="pl-kos">(</span><span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">join</span><span class="pl-kos">(</span><span class="pl-s">' '</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
      <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">setDataValue</span><span class="pl-kos">(</span><span class="pl-s">'firstName'</span><span class="pl-kos">,</span> <span class="pl-s1">firstName</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
      <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">setDataValue</span><span class="pl-kos">(</span><span class="pl-s">'lastName'</span><span class="pl-kos">,</span> <span class="pl-s1">lastName</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-kos">(</span><span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">sync</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-k">let</span> <span class="pl-s1">user</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">firstName</span>: <span class="pl-s">'John'</span><span class="pl-kos">,</span>  <span class="pl-c1">lastName</span>: <span class="pl-s">'Doe'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-c1">fullName</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 'John Doe'</span>
  <span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-c1">fullName</span> <span class="pl-c1">=</span> <span class="pl-s">'Someone Else'</span><span class="pl-kos">;</span>
  <span class="pl-k">await</span> <span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-en">save</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-s1">user</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-c1">firstName</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 'Someone'</span>
  <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-c1">lastName</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 'Else'</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
    </div>
    <pre>&nbsp;</pre>
  </div>
  <h1>Validations &amp; Constraints - 验证 &amp; 约束</h1>
  <p>在本教程中,你将学习如何在 Sequelize 中设置模型的验证和约束.</p>
  <p>对于本教程,将假定以下设置：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> Sequelize<span class="pl-kos">,</span> Op<span class="pl-kos">,</span> Model<span class="pl-kos">,</span> DataTypes <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">"sequelize"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-s">"sqlite::memory:"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">const</span> <span class="pl-v">User</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">"user"</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">username</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">TEXT</span><span class="pl-kos">,</span>
    <span class="pl-c1">allowNull</span>: <span class="pl-c1">false</span><span class="pl-kos">,</span>
    <span class="pl-c1">unique</span>: <span class="pl-c1">true</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">hashedPassword</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">STRING</span><span class="pl-kos">(</span><span class="pl-c1">64</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
    <span class="pl-c1">is</span>: <span class="pl-pds">/<span class="pl-cce">^</span><span class="pl-kos">[</span>0-9a-f<span class="pl-kos">]</span><span class="pl-kos">{</span>64<span class="pl-kos">}</span><span class="pl-cce">$</span>/i</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-kos">(</span><span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">sync</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">force</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-c">// 这是代码</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h2>验证和约束的区别</h2>
  <p>验证是在纯 JavaScript 中在 Sequelize 级别执行的检查. 如果你提供自定义验证器功能,它们可能会非常复杂,也可能是 Sequelize 提供的内置验证器之一. 如果验证失败,则根本不会将 SQL 查询发送到数据库.</p>
  <p>另一方面,约束是在 SQL 级别定义的规则. 约束的最基本示例是唯一约束. 如果约束检查失败,则数据库将引发错误,并且 Sequelize 会将错误转发给 JavaScript(在此示例中,抛出&nbsp;<code>SequelizeUniqueConstraintError</code>). 请注意,在这种情况下,与验证不同,它执行了 SQL 查询.</p>
  <h2>唯一约束</h2>
  <p>下面的代码示例在&nbsp;<code>username</code>&nbsp;字段上定义了唯一约束：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">/* ... */</span> <span class="pl-kos">{</span>
  <span class="pl-c1">username</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">TEXT</span><span class="pl-kos">,</span>
    <span class="pl-c1">allowNull</span>: <span class="pl-c1">false</span><span class="pl-kos">,</span>
    <span class="pl-c1">unique</span>: <span class="pl-c1">true</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
<span class="pl-kos">}</span> <span class="pl-c">/* ... */</span></pre>
  </div>
  <p>同步此模型后(例如,通过调用<code>sequelize.sync</code>),在表中将&nbsp;<code>username</code>&nbsp;字段创建为<code>&nbsp;`name` TEXT UNIQUE</code>,如果尝试插入已存在的用户名将抛出&nbsp;<code>SequelizeUniqueConstraintError</code>.</p>
  <h2>允许/禁止 null 值</h2>
  <p>默认情况下,<code>null</code>&nbsp;是模型每一列的允许值. 可以通过为列设置&nbsp;<code>allowNull: false</code>&nbsp;参数来禁用它,就像在我们的代码示例的&nbsp;<code>username</code>&nbsp;字段中所做的一样：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">/* ... */</span> <span class="pl-kos">{</span>
  <span class="pl-c1">username</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">TEXT</span><span class="pl-kos">,</span>
    <span class="pl-c1">allowNull</span>: <span class="pl-c1">false</span><span class="pl-kos">,</span>
    <span class="pl-c1">unique</span>: <span class="pl-c1">true</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
<span class="pl-kos">}</span> <span class="pl-c">/* ... */</span></pre>
  </div>
  <p>如果没有&nbsp;<code>allowNull: false</code>, 那么调用&nbsp;<code>User.create({})</code>&nbsp;将会生效.</p>
  <h3>关于&nbsp;<code>allowNull</code>&nbsp;实现的说明</h3>
  <p>按照本教程开头所述,<code>allowNull</code>&nbsp;检查是 Sequelize 中唯一由&nbsp;<em>验证</em>&nbsp;和&nbsp;<em>约束</em>&nbsp;混合而成的检查. 这是因为：</p>
  <ul>
    <li>如果试图将&nbsp;<code>null</code>&nbsp;设置到不允许为 null 的字段,则将抛出<code>ValidationError</code>&nbsp;,而且&nbsp;<em>不会执行任何 SQL 查询</em>.</li>
    <li>另外,在&nbsp;<code>sequelize.sync</code>&nbsp;之后,具有&nbsp;<code>allowNull: false</code>&nbsp;的列将使用&nbsp;<code>NOT NULL</code>&nbsp;SQL 约束进行定义. 这样,尝试将值设置为&nbsp;<code>null</code>&nbsp;的直接 SQL 查询也将失败.</li>
  </ul>
  <h2>验证器</h2>
  <p>使用模型验证器,可以为模型的每个属性指定 格式/内容/继承 验证. 验证会自动在&nbsp;<code>create</code>,&nbsp;<code>update</code>&nbsp;和&nbsp;<code>save</code>&nbsp;时运行. 你还可以调用&nbsp;<code>validate()</code>来手动验证实例.</p>
  <h3>按属性验证</h3>
  <p>你可以定义你的自定义验证器,也可以使用由&nbsp;<a href="https://github.com/chriso/validator.js">validator.js (10.11.0)</a>&nbsp;实现的多个内置验证器,如下所示.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'foo'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">bar</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
    <span class="pl-c1">validate</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">is</span>: <span class="pl-pds">/<span class="pl-cce">^</span><span class="pl-kos">[</span>a-z<span class="pl-kos">]</span><span class="pl-c1">+</span><span class="pl-cce">$</span>/i</span><span class="pl-kos">,</span>          <span class="pl-c">// 匹配这个 RegExp</span>
      <span class="pl-c1">is</span>: <span class="pl-kos">[</span><span class="pl-s">"^[a-z]+$"</span><span class="pl-kos">,</span><span class="pl-s">'i'</span><span class="pl-kos">]</span><span class="pl-kos">,</span>     <span class="pl-c">// 与上面相同,但是以字符串构造 RegExp</span>
      <span class="pl-c1">not</span>: <span class="pl-pds">/<span class="pl-cce">^</span><span class="pl-kos">[</span>a-z<span class="pl-kos">]</span><span class="pl-c1">+</span><span class="pl-cce">$</span>/i</span><span class="pl-kos">,</span>         <span class="pl-c">// 不匹配 RegExp</span>
      <span class="pl-c1">not</span>: <span class="pl-kos">[</span><span class="pl-s">"^[a-z]+$"</span><span class="pl-kos">,</span><span class="pl-s">'i'</span><span class="pl-kos">]</span><span class="pl-kos">,</span>    <span class="pl-c">// 与上面相同,但是以字符串构造 RegExp</span>
      <span class="pl-c1">isEmail</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>            <span class="pl-c">// 检查 email 格式 (foo@bar.com)</span>
      <span class="pl-c1">isUrl</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>              <span class="pl-c">// 检查 url 格式 (http://foo.com)</span>
      <span class="pl-c1">isIP</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>               <span class="pl-c">// 检查 IPv4 (129.89.23.1) 或 IPv6 格式</span>
      <span class="pl-c1">isIPv4</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>             <span class="pl-c">// 检查 IPv4 格式 (129.89.23.1)</span>
      <span class="pl-c1">isIPv6</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>             <span class="pl-c">// 检查 IPv6 格式</span>
      <span class="pl-c1">isAlpha</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>            <span class="pl-c">// 只允许字母</span>
      <span class="pl-c1">isAlphanumeric</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>     <span class="pl-c">// 将仅允许使用字母数字,因此 '_abc' 将失败</span>
      <span class="pl-c1">isNumeric</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>          <span class="pl-c">// 只允许数字</span>
      <span class="pl-c1">isInt</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>              <span class="pl-c">// 检查有效的整数</span>
      <span class="pl-c1">isFloat</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>            <span class="pl-c">// 检查有效的浮点数</span>
      <span class="pl-c1">isDecimal</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>          <span class="pl-c">// 检查任何数字</span>
      <span class="pl-c1">isLowercase</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>        <span class="pl-c">// 检查小写</span>
      <span class="pl-c1">isUppercase</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>        <span class="pl-c">// 检查大写</span>
      <span class="pl-c1">notNull</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>            <span class="pl-c">// 不允许为空</span>
      <span class="pl-c1">isNull</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>             <span class="pl-c">// 只允许为空</span>
      <span class="pl-c1">notEmpty</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>           <span class="pl-c">// 不允许空字符串</span>
      <span class="pl-c1">equals</span>: <span class="pl-s">'specific value'</span><span class="pl-kos">,</span> <span class="pl-c">// 仅允许 'specific value'</span>
      <span class="pl-c1">contains</span>: <span class="pl-s">'foo'</span><span class="pl-kos">,</span>          <span class="pl-c">// 强制特定子字符串</span>
      <span class="pl-c1">notIn</span>: <span class="pl-kos">[</span><span class="pl-kos">[</span><span class="pl-s">'foo'</span><span class="pl-kos">,</span> <span class="pl-s">'bar'</span><span class="pl-kos">]</span><span class="pl-kos">]</span><span class="pl-kos">,</span>  <span class="pl-c">// 检查值不是这些之一</span>
      <span class="pl-c1">isIn</span>: <span class="pl-kos">[</span><span class="pl-kos">[</span><span class="pl-s">'foo'</span><span class="pl-kos">,</span> <span class="pl-s">'bar'</span><span class="pl-kos">]</span><span class="pl-kos">]</span><span class="pl-kos">,</span>   <span class="pl-c">// 检查值是其中之一</span>
      <span class="pl-c1">notContains</span>: <span class="pl-s">'bar'</span><span class="pl-kos">,</span>       <span class="pl-c">// 不允许特定的子字符串</span>
      <span class="pl-c1">len</span>: <span class="pl-kos">[</span><span class="pl-c1">2</span><span class="pl-kos">,</span><span class="pl-c1">10</span><span class="pl-kos">]</span><span class="pl-kos">,</span>              <span class="pl-c">// 仅允许长度在2到10之间的值</span>
      <span class="pl-c1">isUUID</span>: <span class="pl-c1">4</span><span class="pl-kos">,</span>                <span class="pl-c">// 只允许 uuid</span>
      <span class="pl-c1">isDate</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>             <span class="pl-c">// 只允许日期字符串</span>
      <span class="pl-c1">isAfter</span>: <span class="pl-s">"2011-11-05"</span><span class="pl-kos">,</span>    <span class="pl-c">// 仅允许特定日期之后的日期字符串</span>
      <span class="pl-c1">isBefore</span>: <span class="pl-s">"2011-11-05"</span><span class="pl-kos">,</span>   <span class="pl-c">// 仅允许特定日期之前的日期字符串</span>
      <span class="pl-c1">max</span>: <span class="pl-c1">23</span><span class="pl-kos">,</span>                  <span class="pl-c">// 仅允许值 &lt;= 23</span>
      <span class="pl-c1">min</span>: <span class="pl-c1">23</span><span class="pl-kos">,</span>                  <span class="pl-c">// 仅允许值 &gt;= 23</span>
      <span class="pl-c1">isCreditCard</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>       <span class="pl-c">// 检查有效的信用卡号</span>

      <span class="pl-c">// 自定义验证器的示例:</span>
      <span class="pl-en">isEven</span><span class="pl-kos">(</span><span class="pl-s1">value</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-en">parseInt</span><span class="pl-kos">(</span><span class="pl-s1">value</span><span class="pl-kos">)</span> % <span class="pl-c1">2</span> !== <span class="pl-c1">0</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
          <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-v">Error</span><span class="pl-kos">(</span><span class="pl-s">'Only even values are allowed!'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>
      <span class="pl-kos">}</span>
      <span class="pl-en">isGreaterThanOtherField</span><span class="pl-kos">(</span><span class="pl-s1">value</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-en">parseInt</span><span class="pl-kos">(</span><span class="pl-s1">value</span><span class="pl-kos">)</span> &lt;= <span class="pl-en">parseInt</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">otherField</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
          <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-v">Error</span><span class="pl-kos">(</span><span class="pl-s">'Bar must be greater than otherField.'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>
      <span class="pl-kos">}</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>请注意,在需要将多个参数传递给内置验证函数的情况下,要传递的参数必须位于数组中. 但是,如果要传递单个数组参数,例如,<code>isIn</code>&nbsp;可接受的字符串数组,则将其解释为多个字符串参数,而不是一个数组参数. 要解决此问题,请传递一个单长度的参数数组,例如上面所示的&nbsp;<code>[['foo', 'bar']]</code>&nbsp;.</p>
  <p>要使用自定义错误消息而不是&nbsp;<a href="https://github.com/chriso/validator.js">validator.js</a>&nbsp;提供的错误消息,请使用对象而不是纯值或参数数组,例如验证器 不需要参数就可以给自定义消息</p>
  <div class="highlight highlight-source-js">
<pre>isInt: <span class="pl-kos">{</span>
  <span class="pl-c1">msg</span>: <span class="pl-s">"必须是价格的整数"</span>
<span class="pl-kos">}</span></pre>
  </div>
  <p>或者如果还需要传递参数,则添加一个&nbsp;<code>args</code>&nbsp;属性：</p>
  <div class="highlight highlight-source-js">
<pre>isIn: <span class="pl-kos">{</span>
  <span class="pl-c1">args</span>: <span class="pl-kos">[</span><span class="pl-kos">[</span><span class="pl-s">'en'</span><span class="pl-kos">,</span> <span class="pl-s">'zh'</span><span class="pl-kos">]</span><span class="pl-kos">]</span><span class="pl-kos">,</span>
  <span class="pl-c1">msg</span>: <span class="pl-s">"必须为英文或中文"</span>
<span class="pl-kos">}</span></pre>
  </div>
  <p>使用自定义验证器功能时,错误消息将是抛出的&nbsp;<code>Error</code>&nbsp;对象所持有的任何消息.</p>
  <p>有关内置验证方法的更多详细信息,请参见<a href="https://github.com/chriso/validator.js">validator.js 项目</a>.</p>
  <p><strong>提示:</strong>&nbsp;你还可以为日志记录部分定义自定义功能. 只需传递一个函数. 第一个参数是记录的字符串.</p>
  <h3><code>allowNull</code>&nbsp;与其他验证器的交互</h3>
  <p>如果将模型的特定字段设置为不允许为 null(使用&nbsp;<code>allowNull: false</code>),并且该值已设置为&nbsp;<code>null</code>,则将跳过所有验证器,并抛出&nbsp;<code>ValidationError</code>.</p>
  <p>另一方面,如果将其设置为允许 null(使用&nbsp;<code>allowNull: true</code>),并且该值已设置为&nbsp;<code>null</code>,则仅会跳过内置验证器,而自定义验证器仍将运行.</p>
  <p>举例来说,这意味着你可以拥有一个字符串字段,该字段用于验证其长度在5到10个字符之间,但也允许使用&nbsp;<code>null</code>&nbsp;(因为当该值为&nbsp;<code>null</code>&nbsp;时,长度验证器将被自动跳过)：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">class</span> <span class="pl-v">User</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">username</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
    <span class="pl-c1">allowNull</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
    <span class="pl-c1">validate</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">len</span>: <span class="pl-kos">[</span><span class="pl-c1">5</span><span class="pl-kos">,</span> <span class="pl-c1">10</span><span class="pl-kos">]</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> sequelize <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>你也可以使用自定义验证器有条件地允许&nbsp;<code>null</code>&nbsp;值,因为不会跳过它：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">class</span> <span class="pl-v">User</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">age</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
  <span class="pl-c1">name</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
    <span class="pl-c1">allowNull</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
    <span class="pl-c1">validate</span>: <span class="pl-kos">{</span>
      <span class="pl-en">customValidator</span><span class="pl-kos">(</span><span class="pl-s1">value</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">value</span> <span class="pl-c1">===</span> <span class="pl-c1">null</span> <span class="pl-c1">&amp;&amp;</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">age</span> !== <span class="pl-c1">10</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
          <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-v">Error</span><span class="pl-kos">(</span><span class="pl-s">"除非年龄为10,否则名称不能为 null"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>
      <span class="pl-kos">}</span><span class="pl-kos">)</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> sequelize <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>你可以通过设置&nbsp;<code>notNull</code>&nbsp;验证器来自定义&nbsp;<code>allowNull</code>&nbsp;错误消息：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">class</span> <span class="pl-v">User</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">name</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
    <span class="pl-c1">allowNull</span>: <span class="pl-c1">false</span><span class="pl-kos">,</span>
    <span class="pl-c1">validate</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">notNull</span>: <span class="pl-kos">{</span>
        <span class="pl-c1">msg</span>: <span class="pl-s">'请输入你的名字'</span>
      <span class="pl-kos">}</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> sequelize <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h3>模型范围内的验证</h3>
  <p>还可以定义验证,来在特定于字段的验证器之后检查模型. 例如,使用此方法,可以确保既未设置&nbsp;<code>latitude</code>&nbsp;和&nbsp;<code>longitude</code>,又未同时设置两者. 如果设置了一个但未设置另一个,则失败.</p>
  <p>使用模型对象的上下文调用模型验证器方法,如果它们抛出错误,则认为失败,否则将通过. 这与自定义字段特定的验证器相同.</p>
  <p>所收集的任何错误消息都将与字段验证错误一起放入验证结果对象中,其关键字以&nbsp;<code>validate</code>&nbsp;选项对象中验证方法失败的键命名. 即便在任何时候每种模型验证方法都只有一个错误消息,但它会在数组中显示为单个字符串错误,以最大程度地提高与字段错误的一致性.</p>
  <p>一个例子:</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">class</span> <span class="pl-v">Place</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">Place</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">name</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">address</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">latitude</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
    <span class="pl-c1">validate</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">min</span>: <span class="pl-c1">-</span><span class="pl-c1">90</span><span class="pl-kos">,</span>
      <span class="pl-c1">max</span>: <span class="pl-c1">90</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">longitude</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
    <span class="pl-c1">validate</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">min</span>: <span class="pl-c1">-</span><span class="pl-c1">180</span><span class="pl-kos">,</span>
      <span class="pl-c1">max</span>: <span class="pl-c1">180</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  sequelize<span class="pl-kos">,</span>
  <span class="pl-c1">validate</span>: <span class="pl-kos">{</span>
    <span class="pl-en">bothCoordsOrNone</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">latitude</span> <span class="pl-c1">===</span> <span class="pl-c1">null</span><span class="pl-kos">)</span> !== <span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">longitude</span> <span class="pl-c1">===</span> <span class="pl-c1">null</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-v">Error</span><span class="pl-kos">(</span><span class="pl-s">'Either both latitude and longitude, or neither!'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
      <span class="pl-kos">}</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span></pre>
  </div>
  <p>在这种简单的情况下,如果只给定了纬度或经度,而不是同时给出两者, 则不能验证对象. 如果我们尝试构建一个超出范围的纬度且没有经度的对象,则<code>somePlace.validate()</code>&nbsp;可能会返回：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-kos">{</span>
  <span class="pl-s">'latitude'</span>: <span class="pl-kos">[</span><span class="pl-s">'Invalid number: latitude'</span><span class="pl-kos">]</span><span class="pl-kos">,</span>
  <span class="pl-s">'bothCoordsOrNone'</span>: <span class="pl-kos">[</span><span class="pl-s">'Either both latitude and longitude, or neither!'</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span></pre>
  </div>
  <p>也可以使用在单个属性上定义的自定义验证程序(例如&nbsp;<code>latitude</code>&nbsp;属性,通过检查&nbsp;<code>(value === null) !== (this.longitude === null)</code>&nbsp;)来完成此类验证, 但模型范围内的验证方法更为简洁.</p>
</div>
<p>&nbsp;</p>
<h1>Raw Queries - 原始查询</h1>
<p>由于常常使用简单的方式来执行原始/已经准备好的SQL查询,因此可以使用&nbsp;<code>sequelize.query</code>&nbsp;方法.</p>
<p>默认情况下,函数将返回两个参数 - 一个结果数组,以及一个包含元数据(例如受影响的行数等)的对象. 请注意,由于这是一个原始查询,所以元数据都是具体的方言. 某些方言返回元数据 "within" 结果对象(作为数组上的属性). 但是,将永远返回两个参数,但对于MSSQL和MySQL,它将是对同一对象的两个引用.</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">[</span><span class="pl-s1">results</span><span class="pl-kos">,</span> <span class="pl-s1">metadata</span><span class="pl-kos">]</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">query</span><span class="pl-kos">(</span><span class="pl-s">"UPDATE users SET y = 42 WHERE x = 12"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 结果将是一个空数组,元数据将包含受影响的行数.</span></pre>
</div>
<p>在不需要访问元数据的情况下,你可以传递一个查询类型来告诉后续如何格式化结果. 例如,对于一个简单的选择查询你可以做:</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> QueryTypes <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'sequelize'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">users</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">query</span><span class="pl-kos">(</span><span class="pl-s">"SELECT * FROM `users`"</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">type</span>: <span class="pl-v">QueryTypes</span><span class="pl-kos">.</span><span class="pl-c1">SELECT</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 我们不需要在这里分解结果 - 结果会直接返回</span></pre>
</div>
<p>还有其他几种查询类型可用.&nbsp;<a href="https://github.com/sequelize/sequelize/blob/master/lib/query-types.js">详细了解来源</a></p>
<p>第二种选择是模型. 如果传递模型,返回的数据将是该模型的实例.</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-c">// Callee 是模型定义. 这样你就可以轻松地将查询映射到预定义的模型</span>
<span class="pl-k">const</span> <span class="pl-s1">projects</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">query</span><span class="pl-kos">(</span><span class="pl-s">'SELECT * FROM projects'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">model</span>: <span class="pl-v">Projects</span><span class="pl-kos">,</span>
  <span class="pl-c1">mapToModel</span>: <span class="pl-c1">true</span> <span class="pl-c">// 如果你有任何映射字段,则在此处传递 true</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 现在,`projects` 的每个元素都是 Project 的一个实例</span></pre>
</div>
<p>查看&nbsp;<a href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/class/lib/sequelize.js~Sequelize.html#instance-method-query">Query API 参考</a>中的更多参数. 以下是一些例子:</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> QueryTypes <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'sequelize'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">query</span><span class="pl-kos">(</span><span class="pl-s">'SELECT 1'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c">// 用于记录查询的函数(或false)</span>
  <span class="pl-c">// 将调用发送到服务器的每个SQL查询.</span>
  <span class="pl-c1">logging</span>: <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-c1">log</span><span class="pl-kos">,</span>

  <span class="pl-c">// 如果plain为true,则sequelize将仅返回结果集的第一条记录. </span>
  <span class="pl-c">// 如果是false,它将返回所有记录.</span>
  <span class="pl-c1">plain</span>: <span class="pl-c1">false</span><span class="pl-kos">,</span>

  <span class="pl-c">// 如果你没有查询的模型定义,请将此项设置为true.</span>
  <span class="pl-c1">raw</span>: <span class="pl-c1">false</span><span class="pl-kos">,</span>

  <span class="pl-c">// 你正在执行的查询类型. 查询类型会影响结果在传回之前的格式.</span>
  <span class="pl-c1">type</span>: <span class="pl-v">QueryTypes</span><span class="pl-kos">.</span><span class="pl-c1">SELECT</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 注意第二个参数为null！</span>
<span class="pl-c">// 即使我们在这里声明了一个被调用对象,</span>
<span class="pl-c">// raw: true 也会取代并返回一个原始对象.</span>

<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">query</span><span class="pl-kos">(</span><span class="pl-s">'SELECT * FROM projects'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">raw</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h2><a id="user-content-dotted-属性-和-nest-参数" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/raw-queries.md#dotted-%E5%B1%9E%E6%80%A7-%E5%92%8C-nest-%E5%8F%82%E6%95%B0" aria-hidden="true"></a>"Dotted" 属性 和&nbsp;<code>nest</code>&nbsp;参数</h2>
<p>如果表的属性名称包含点,则可以通过设置&nbsp;<code>nest: true</code>&nbsp;参数将生成的对象变为嵌套对象. 这可以通过&nbsp;<a href="https://github.com/mickhansen/dottie.js/">dottie.js</a>&nbsp;在后台实现. 见下文：</p>
<ul>
  <li>
    <p>不使用&nbsp;<code>nest: true</code>:</p>
    <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> QueryTypes <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'sequelize'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">records</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">query</span><span class="pl-kos">(</span><span class="pl-s">'select 1 as `foo.bar.baz`'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">type</span>: <span class="pl-v">QueryTypes</span><span class="pl-kos">.</span><span class="pl-c1">SELECT</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-c1">JSON</span><span class="pl-kos">.</span><span class="pl-en">stringify</span><span class="pl-kos">(</span><span class="pl-s1">records</span><span class="pl-kos">[</span><span class="pl-c1">0</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-c1">null</span><span class="pl-kos">,</span> <span class="pl-c1">2</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
    </div>
    <div class="highlight highlight-source-json">
<pre>{
  <span class="pl-s"><span class="pl-pds">"</span>foo.bar.baz<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>
}</pre>
    </div>
  </li>
  <li>
    <p>使用&nbsp;<code>nest: true</code>:</p>
    <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> QueryTypes <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'sequelize'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">records</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">query</span><span class="pl-kos">(</span><span class="pl-s">'select 1 as `foo.bar.baz`'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">nest</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
  <span class="pl-c1">type</span>: <span class="pl-v">QueryTypes</span><span class="pl-kos">.</span><span class="pl-c1">SELECT</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-c1">JSON</span><span class="pl-kos">.</span><span class="pl-en">stringify</span><span class="pl-kos">(</span><span class="pl-s1">records</span><span class="pl-kos">[</span><span class="pl-c1">0</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-c1">null</span><span class="pl-kos">,</span> <span class="pl-c1">2</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
    </div>
    <div class="highlight highlight-source-json">
<pre>{
  <span class="pl-s"><span class="pl-pds">"</span>foo<span class="pl-pds">"</span></span>: {
    <span class="pl-s"><span class="pl-pds">"</span>bar<span class="pl-pds">"</span></span>: {
      <span class="pl-s"><span class="pl-pds">"</span>baz<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>
    }
  }
}</pre>
    </div>
  </li>
</ul>
<h2><a id="user-content-替换" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/raw-queries.md#%E6%9B%BF%E6%8D%A2" aria-hidden="true"></a>替换</h2>
<p>查询中的替换可以通过两种不同的方式完成:使用命名参数(以<code>:</code>开头),或者由<code>？</code>表示的未命名参数. 替换在options对象中传递.</p>
<ul>
  <li>如果传递一个数组,&nbsp;<code>?</code>&nbsp;将按照它们在数组中出现的顺序被替换</li>
  <li>如果传递一个对象,&nbsp;<code>:key</code>&nbsp;将替换为该对象的键. 如果对象包含在查询中找不到的键,则会抛出异常,反之亦然.</li>
</ul>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> QueryTypes <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'sequelize'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">query</span><span class="pl-kos">(</span>
  <span class="pl-s">'SELECT * FROM projects WHERE status = ?'</span><span class="pl-kos">,</span>
  <span class="pl-kos">{</span>
    <span class="pl-c1">replacements</span>: <span class="pl-kos">[</span><span class="pl-s">'active'</span><span class="pl-kos">]</span><span class="pl-kos">,</span>
    <span class="pl-c1">type</span>: <span class="pl-v">QueryTypes</span><span class="pl-kos">.</span><span class="pl-c1">SELECT</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">query</span><span class="pl-kos">(</span>
  <span class="pl-s">'SELECT * FROM projects WHERE status = :status'</span><span class="pl-kos">,</span>
  <span class="pl-kos">{</span>
    <span class="pl-c1">replacements</span>: <span class="pl-kos">{</span> <span class="pl-c1">status</span>: <span class="pl-s">'active'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-c1">type</span>: <span class="pl-v">QueryTypes</span><span class="pl-kos">.</span><span class="pl-c1">SELECT</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>数组替换将自动处理,以下查询将搜索状态与值数组匹配的项目.</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> QueryTypes <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'sequelize'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">query</span><span class="pl-kos">(</span>
  <span class="pl-s">'SELECT * FROM projects WHERE status IN(:status)'</span><span class="pl-kos">,</span>
  <span class="pl-kos">{</span>
    <span class="pl-c1">replacements</span>: <span class="pl-kos">{</span> <span class="pl-c1">status</span>: <span class="pl-kos">[</span><span class="pl-s">'active'</span><span class="pl-kos">,</span> <span class="pl-s">'inactive'</span><span class="pl-kos">]</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-c1">type</span>: <span class="pl-v">QueryTypes</span><span class="pl-kos">.</span><span class="pl-c1">SELECT</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>要使用通配符运算符&nbsp;<code>％</code>,请将其附加到你的替换中. 以下查询与名称以 'ben' 开头的用户相匹配.</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> QueryTypes <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'sequelize'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">query</span><span class="pl-kos">(</span>
  <span class="pl-s">'SELECT * FROM users WHERE name LIKE :search_name'</span><span class="pl-kos">,</span>
  <span class="pl-kos">{</span>
    <span class="pl-c1">replacements</span>: <span class="pl-kos">{</span> <span class="pl-c1">search_name</span>: <span class="pl-s">'ben%'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-c1">type</span>: <span class="pl-v">QueryTypes</span><span class="pl-kos">.</span><span class="pl-c1">SELECT</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h2><a id="user-content-绑定参数" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/raw-queries.md#%E7%BB%91%E5%AE%9A%E5%8F%82%E6%95%B0" aria-hidden="true"></a>绑定参数</h2>
<p>绑定参数就像替换. 除非替换被转义并在查询发送到数据库之前通过后续插入到查询中,而将绑定参数发送到SQL查询文本之外的数据库. 查询可以具有绑定参数或替换.绑定参数由&nbsp;<code>$1, $2, ... (numeric)</code>&nbsp;或&nbsp;<code>$key (alpha-numeric)</code>&nbsp;引用.这是独立于方言的.</p>
<ul>
  <li>如果传递一个数组,&nbsp;<code>$1</code>&nbsp;被绑定到数组中的第一个元素 (<code>bind[0]</code>).</li>
  <li>如果传递一个对象,&nbsp;<code>$key</code>&nbsp;绑定到&nbsp;<code>object['key']</code>. 每个键必须以非数字字符开始.&nbsp;<code>$1</code>&nbsp;不是一个有效的键,即使&nbsp;<code>object['1']</code>&nbsp;存在.</li>
  <li>在这两种情况下&nbsp;<code>$$</code>&nbsp;可以用来转义一个&nbsp;<code>$</code>&nbsp;字符符号.</li>
</ul>
<p>数组或对象必须包含所有绑定的值,或者Sequelize将抛出异常. 这甚至适用于数据库可能忽略绑定参数的情况.</p>
<p>数据库可能会增加进一步的限制. 绑定参数不能是SQL关键字,也不能是表或列名. 引用的文本或数据也忽略它们. 在PostgreSQL中,如果不能从上下文&nbsp;<code>$1::varchar</code>&nbsp;推断类型,那么也可能需要对其进行类型转换.</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> QueryTypes <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'sequelize'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">query</span><span class="pl-kos">(</span>
  <span class="pl-s">'SELECT *, "text with literal $$1 and literal $$status" as t FROM projects WHERE status = $1'</span><span class="pl-kos">,</span>
  <span class="pl-kos">{</span>
    <span class="pl-c1">bind</span>: <span class="pl-kos">[</span><span class="pl-s">'active'</span><span class="pl-kos">]</span><span class="pl-kos">,</span>
    <span class="pl-c1">type</span>: <span class="pl-v">QueryTypes</span><span class="pl-kos">.</span><span class="pl-c1">SELECT</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">query</span><span class="pl-kos">(</span>
  <span class="pl-s">'SELECT *, "text with literal $$1 and literal $$status" as t FROM projects WHERE status = $status'</span><span class="pl-kos">,</span>
  <span class="pl-kos">{</span>
    <span class="pl-c1">bind</span>: <span class="pl-kos">{</span> <span class="pl-c1">status</span>: <span class="pl-s">'active'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-c1">type</span>: <span class="pl-v">QueryTypes</span><span class="pl-kos">.</span><span class="pl-c1">SELECT</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">)</span><span class="pl-kos">;<br /><br /></span></pre>
  <h1>Associations - 关联</h1>
  <p>Sequelize 支持标准关联关系:&nbsp;<a href="https://en.wikipedia.org/wiki/One-to-one_%28data_model%29" rel="nofollow">一对一</a>,&nbsp;<a href="https://en.wikipedia.org/wiki/One-to-many_%28data_model%29" rel="nofollow">一对多</a>&nbsp;和&nbsp;<a href="https://en.wikipedia.org/wiki/Many-to-many_%28data_model%29" rel="nofollow">多对多</a>.</p>
  <p>为此,Sequelize 提供了&nbsp;<strong>四种</strong>&nbsp;关联类型,并将它们组合起来以创建关联：</p>
  <ul>
    <li><code>HasOne</code>&nbsp;关联类型</li>
    <li><code>BelongsTo</code>&nbsp;关联类型</li>
    <li><code>HasMany</code>&nbsp;关联类型</li>
    <li><code>BelongsToMany</code>&nbsp;关联类型</li>
  </ul>
  <p>该指南将讲解如何定义这四种类型的关联,然后讲解如何将它们组合来定义三种标准关联类型(<a href="https://en.wikipedia.org/wiki/One-to-one_%28data_model%29" rel="nofollow">一对一</a>,&nbsp;<a href="https://en.wikipedia.org/wiki/One-to-many_%28data_model%29" rel="nofollow">一对多</a>&nbsp;和&nbsp;<a href="https://en.wikipedia.org/wiki/Many-to-many_%28data_model%29" rel="nofollow">多对多</a>).</p>
  <h2><a id="user-content-定义-sequelize-关联" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E5%AE%9A%E4%B9%89-sequelize-%E5%85%B3%E8%81%94" aria-hidden="true"></a>定义 Sequelize 关联</h2>
  <p>四种关联类型的定义非常相似. 假设我们有两个模型&nbsp;<code>A</code>&nbsp;和&nbsp;<code>B</code>. 告诉 Sequelize 两者之间的关联仅需要调用一个函数：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">A</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'A'</span><span class="pl-kos">,</span> <span class="pl-c">/* ... */</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">B</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'B'</span><span class="pl-kos">,</span> <span class="pl-c">/* ... */</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-v">A</span><span class="pl-kos">.</span><span class="pl-en">hasOne</span><span class="pl-kos">(</span><span class="pl-v">B</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// A 有一个 B</span>
<span class="pl-v">A</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">B</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// A 属于 B</span>
<span class="pl-v">A</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">B</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// A 有多个 B</span>
<span class="pl-v">A</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">B</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-s">'C'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// A 属于多个 B , 通过联结表 C</span></pre>
  </div>
  <p>它们都接受一个对象作为第二个参数(前三个参数是可选的,而对于包含&nbsp;<code>through</code>&nbsp;属性的&nbsp;<code>belongsToMany</code>&nbsp;是必需的)： They all accept an options object as a second parameter</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">A</span><span class="pl-kos">.</span><span class="pl-en">hasOne</span><span class="pl-kos">(</span><span class="pl-v">B</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c">/* 参数 */</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">A</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">B</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c">/* 参数 */</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">A</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">B</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c">/* 参数 */</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">A</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">B</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-s">'C'</span><span class="pl-kos">,</span> <span class="pl-c">/* 参数 */</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>关联的定义顺序是有关系的. 换句话说,对于这四种情况,定义顺序很重要. 在上述所有示例中,<code>A</code>&nbsp;称为&nbsp;<strong>源</strong>&nbsp;模型,而&nbsp;<code>B</code>&nbsp;称为&nbsp;<strong>目标</strong>&nbsp;模型. 此术语很重要.</p>
  <p><code>A.hasOne(B)</code>&nbsp;关联意味着&nbsp;<code>A</code>&nbsp;和&nbsp;<code>B</code>&nbsp;之间存在一对一的关系,外键在目标模型(<code>B</code>)中定义.</p>
  <p><code>A.belongsTo(B)</code>关联意味着&nbsp;<code>A</code>&nbsp;和&nbsp;<code>B</code>&nbsp;之间存在一对一的关系,外键在源模型中定义(<code>A</code>).</p>
  <p><code>A.hasMany(B)</code>&nbsp;关联意味着&nbsp;<code>A</code>&nbsp;和&nbsp;<code>B</code>&nbsp;之间存在一对多关系,外键在目标模型(<code>B</code>)中定义.</p>
  <p>这三个调用将导致 Sequelize 自动将外键添加到适当的模型中(除非它们已经存在).</p>
  <p><code>A.belongsToMany(B, { through: 'C' })</code>&nbsp;关联意味着将表&nbsp;<code>C</code>&nbsp;用作<a href="https://en.wikipedia.org/wiki/Associative_entity" rel="nofollow">联结表</a>,在&nbsp;<code>A</code>&nbsp;和&nbsp;<code>B</code>&nbsp;之间存在多对多关系. 具有外键(例如,<code>aId</code>&nbsp;和&nbsp;<code>bId</code>). Sequelize 将自动创建此模型&nbsp;<code>C</code>(除非已经存在),并在其上定义适当的外键.</p>
  <p><em>注意：在上面的&nbsp;<code>belongsToMany</code>&nbsp;示例中,字符串(<code>'C'</code>)被传递给&nbsp;<code>through</code>&nbsp;参数. 在这种情况下,Sequelize 会自动使用该名称生成模型. 但是,如果已经定义了模型,也可以直接传递模型.</em></p>
  <p>这些是每种关联类型中涉及的主要思想. 但是,这些关系通常成对使用,以便 Sequelize 更好地使用. 这将在后文中看到.</p>
  <h2><a id="user-content-创建标准关系" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E5%88%9B%E5%BB%BA%E6%A0%87%E5%87%86%E5%85%B3%E7%B3%BB" aria-hidden="true"></a>创建标准关系</h2>
  <p>如前所述,Sequelize 关联通常成对定义. 综上所述：</p>
  <ul>
    <li>创建一个&nbsp;<strong>一对一</strong>&nbsp;关系,&nbsp;<code>hasOne</code>&nbsp;和&nbsp;<code>belongsTo</code>&nbsp;关联一起使用;</li>
    <li>创建一个&nbsp;<strong>一对多</strong>&nbsp;关系,&nbsp;<code>hasMany</code>&nbsp;he&nbsp;<code>belongsTo</code>&nbsp;关联一起使用;</li>
    <li>创建一个&nbsp;<strong>多对多</strong>&nbsp;关系, 两个&nbsp;<code>belongsToMany</code>&nbsp;调用一起使用.
      <ul>
        <li>注意: 还有一个&nbsp;<em>超级多对多</em>&nbsp;关系,一次使用六个关联,将在<a href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/advanced-many-to-many.md">高级多对多关系指南</a>中进行讨论.</li>
      </ul>
    </li>
  </ul>
  <p>接下来将进行详细介绍. 本章末尾将讨论使用这些成对而不是单个关联的优点.</p>
  <h2><a id="user-content-一对一关系" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E4%B8%80%E5%AF%B9%E4%B8%80%E5%85%B3%E7%B3%BB" aria-hidden="true"></a>一对一关系</h2>
  <h3><a id="user-content-哲理" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E5%93%B2%E7%90%86" aria-hidden="true"></a>哲理</h3>
  <p>在深入探讨使用 Sequelize 的各个方面之前,退后一步来考虑一对一关系会发生什么是很有用的.</p>
  <p>假设我们有两个模型,<code>Foo</code>&nbsp;和&nbsp;<code>Bar</code>.我们要在 Foo 和 Bar 之间建立一对一的关系.我们知道在关系数据库中,这将通过在其中一个表中建立外键来完成.因此,在这种情况下,一个非常关键的问题是：我们希望该外键在哪个表中？换句话说,我们是要 <code>Foo</code>&nbsp;拥有&nbsp;<code>barId</code>&nbsp;列,还是&nbsp;<code>Bar</code>&nbsp;应当拥有&nbsp;<code>fooId</code>列？</p>
  <p>原则上,这两个选择都是在 Foo 和 Bar 之间建立一对一关系的有效方法.但是,当我们说&nbsp;<em>"Foo 和 Bar 之间存在一对一关系"</em>&nbsp;时,尚不清楚该关系是&nbsp;<em>强制性</em>&nbsp;的还是可选的.换句话说,Foo 是否可以没有 Bar 而存在？ Foo 的 Bar 可以存在吗？这些问题的答案有助于帮我们弄清楚外键列在哪里.</p>
  <h3><a id="user-content-目标" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E7%9B%AE%E6%A0%87" aria-hidden="true"></a>目标</h3>
  <p>对于本示例的其余部分,我们假设我们有两个模型,即&nbsp;<code>Foo</code>&nbsp;和&nbsp;<code>Bar</code>. 我们想要在它们之间建立一对一的关系,以便&nbsp;<code>Bar</code>&nbsp;获得&nbsp;<code>fooId</code>&nbsp;列.</p>
  <h3><a id="user-content-实践" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E5%AE%9E%E8%B7%B5" aria-hidden="true"></a>实践</h3>
  <p>实现该目标的主要设置如下：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">hasOne</span><span class="pl-kos">(</span><span class="pl-v">Bar</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Bar</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Foo</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>由于未传递任何参数,因此 Sequelize 将从模型名称中推断出要做什么. 在这种情况下,Sequelize 知道必须将&nbsp;<code>fooId</code>&nbsp;列添加到&nbsp;<code>Bar</code>&nbsp;中.</p>
  <p>这样,在上述代码之后调用&nbsp;<code>Bar.sync()</code>&nbsp;将产生以下 SQL(例如,在PostgreSQL上)：</p>
  <div class="highlight highlight-source-sql">
<pre><span class="pl-k">CREATE</span> <span class="pl-k">TABLE</span> <span class="pl-en">IF</span> NOT EXISTS <span class="pl-s"><span class="pl-pds">"</span>foos<span class="pl-pds">"</span></span> (
  <span class="pl-c">/* ... */</span>
);
<span class="pl-k">CREATE</span> <span class="pl-k">TABLE</span> <span class="pl-en">IF</span> NOT EXISTS <span class="pl-s"><span class="pl-pds">"</span>bars<span class="pl-pds">"</span></span> (
  <span class="pl-c">/* ... */</span>
  <span class="pl-s"><span class="pl-pds">"</span>fooId<span class="pl-pds">"</span></span> <span class="pl-k">INTEGER</span> <span class="pl-k">REFERENCES</span> <span class="pl-s"><span class="pl-pds">"</span>foos<span class="pl-pds">"</span></span> (<span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>) <span class="pl-k">ON DELETE</span> <span class="pl-k">SET</span> <span class="pl-k">NULL</span> <span class="pl-k">ON</span> <span class="pl-k">UPDATE</span> CASCADE
  <span class="pl-c">/* ... */</span>
);</pre>
  </div>
  <h3><a id="user-content-参数" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E5%8F%82%E6%95%B0" aria-hidden="true"></a>参数</h3>
  <p>可以将各种参数作为关联调用的第二个参数传递.</p>
  <h4><a id="user-content-ondelete-和-onupdate" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#ondelete-%E5%92%8C-onupdate" aria-hidden="true"></a><code>onDelete</code>&nbsp;和&nbsp;<code>onUpdate</code></h4>
  <p>例如,要配置&nbsp;<code>ON DELETE</code>&nbsp;和&nbsp;<code>ON UPDATE</code>&nbsp;行为,你可以执行以下操作：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">hasOne</span><span class="pl-kos">(</span><span class="pl-v">Bar</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">onDelete</span>: <span class="pl-s">'RESTRICT'</span><span class="pl-kos">,</span>
  <span class="pl-c1">onUpdate</span>: <span class="pl-s">'RESTRICT'</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Bar</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Foo</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>可用的参数为&nbsp;<code>RESTRICT</code>,&nbsp;<code>CASCADE</code>,&nbsp;<code>NO ACTION</code>,&nbsp;<code>SET DEFAULT</code>&nbsp;和&nbsp;<code>SET NULL</code>.</p>
  <p>一对一关联的默认值,&nbsp;<code>ON DELETE</code>&nbsp;为&nbsp;<code>SET NULL</code>&nbsp;而&nbsp;<code>ON UPDATE</code>&nbsp;为&nbsp;<code>CASCADE</code>.</p>
  <h4><a id="user-content-自定义外键" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%A4%96%E9%94%AE" aria-hidden="true"></a>自定义外键</h4>
  <p>上面显示的&nbsp;<code>hasOne</code>&nbsp;和&nbsp;<code>belongsTo</code>&nbsp;调用都会推断出要创建的外键应称为&nbsp;<code>fooId</code>. 如要使用其他名称,例如&nbsp;<code>myFooId</code>：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 方法 1</span>
<span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">hasOne</span><span class="pl-kos">(</span><span class="pl-v">Bar</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">foreignKey</span>: <span class="pl-s">'myFooId'</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Bar</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Foo</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 方法 2</span>
<span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">hasOne</span><span class="pl-kos">(</span><span class="pl-v">Bar</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">foreignKey</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">name</span>: <span class="pl-s">'myFooId'</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Bar</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Foo</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 方法 3</span>
<span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">hasOne</span><span class="pl-kos">(</span><span class="pl-v">Bar</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Bar</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Foo</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">foreignKey</span>: <span class="pl-s">'myFooId'</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 方法 4</span>
<span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">hasOne</span><span class="pl-kos">(</span><span class="pl-v">Bar</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Bar</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Foo</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">foreignKey</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">name</span>: <span class="pl-s">'myFooId'</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>如上所示,<code>foreignKey</code>&nbsp;参数接受一个字符串或一个对象. 当接收到一个对象时,该对象将用作列的定义,就像在标准的&nbsp;<code>sequelize.define</code>&nbsp;调用中所做的一样. 因此,指定诸如&nbsp;<code>type</code>,&nbsp;<code>allowNull</code>,&nbsp;<code>defaultValue</code>&nbsp;等参数就可以了.</p>
  <p>例如,要使用&nbsp;<code>UUID</code>&nbsp;作为外键数据类型而不是默认值(<code>INTEGER</code>),只需执行以下操作：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> DataTypes <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">"Sequelize"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">hasOne</span><span class="pl-kos">(</span><span class="pl-v">Bar</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">foreignKey</span>: <span class="pl-kos">{</span>
    <span class="pl-c">// name: 'myFooId'</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">UUID</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Bar</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Foo</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h4><a id="user-content-强制性与可选性关联" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E5%BC%BA%E5%88%B6%E6%80%A7%E4%B8%8E%E5%8F%AF%E9%80%89%E6%80%A7%E5%85%B3%E8%81%94" aria-hidden="true"></a>强制性与可选性关联</h4>
  <p>默认情况下,该关联被视为可选. 换句话说,在我们的示例中,<code>fooId</code>&nbsp;允许为空,这意味着一个 Bar 可以不存在 Foo 而存在. 只需在外键选项中指定&nbsp;<code>allowNull: false</code>&nbsp;即可更改此设置：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">hasOne</span><span class="pl-kos">(</span><span class="pl-v">Bar</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">foreignKey</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">allowNull</span>: <span class="pl-c1">false</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// "fooId" INTEGER NOT NULL REFERENCES "foos" ("id") ON DELETE RESTRICT ON UPDATE RESTRICT</span></pre>
  </div>
  <h2><a id="user-content-一对多关系" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E4%B8%80%E5%AF%B9%E5%A4%9A%E5%85%B3%E7%B3%BB" aria-hidden="true"></a>一对多关系</h2>
  <h3><a id="user-content-原理" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E5%8E%9F%E7%90%86" aria-hidden="true"></a>原理</h3>
  <p>一对多关联将一个源与多个目标连接,而所有这些目标仅与此单个源连接.</p>
  <p>这意味着,与我们必须选择放置外键的一对一关联不同,在一对多关联中只有一个选项. 例如,如果一个 Foo 有很多 Bar(因此每个 Bar 都属于一个 Foo),那么唯一明智的方式就是在&nbsp;<code>Bar</code>&nbsp;表中有一个&nbsp;<code>fooId</code>&nbsp;列. 而反过来是不可能的,因为一个&nbsp;<code>Foo</code>&nbsp;会有很多&nbsp;<code>Bar</code>.</p>
  <h3><a id="user-content-目标-1" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E7%9B%AE%E6%A0%87-1" aria-hidden="true"></a>目标</h3>
  <p>在这个例子中,我们有模型&nbsp;<code>Team</code>&nbsp;和&nbsp;<code>Player</code>. 我们要告诉 Sequelize,他们之间存在一对多的关系,这意味着一个 Team 有 Player ,而每个 Player 都属于一个 Team.</p>
  <h3><a id="user-content-实践-1" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E5%AE%9E%E8%B7%B5-1" aria-hidden="true"></a>实践</h3>
  <p>这样做的主要方法如下：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Team</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Player</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Player</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Team</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>同样,实现此目标的主要方法是使用一对 Sequelize 关联(<code>hasMany</code>&nbsp;和&nbsp;<code>belongsTo</code>).</p>
  <p>例如,在 PostgreSQL 中,以上设置将在&nbsp;<code>sync()</code>&nbsp;之后产生以下 SQL：</p>
  <div class="highlight highlight-source-sql">
<pre><span class="pl-k">CREATE</span> <span class="pl-k">TABLE</span> <span class="pl-en">IF</span> NOT EXISTS <span class="pl-s"><span class="pl-pds">"</span>Teams<span class="pl-pds">"</span></span> (
  <span class="pl-c">/* ... */</span>
);
<span class="pl-k">CREATE</span> <span class="pl-k">TABLE</span> <span class="pl-en">IF</span> NOT EXISTS <span class="pl-s"><span class="pl-pds">"</span>Players<span class="pl-pds">"</span></span> (
  <span class="pl-c">/* ... */</span>
  <span class="pl-s"><span class="pl-pds">"</span>TeamId<span class="pl-pds">"</span></span> <span class="pl-k">INTEGER</span> <span class="pl-k">REFERENCES</span> <span class="pl-s"><span class="pl-pds">"</span>Teams<span class="pl-pds">"</span></span> (<span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>) <span class="pl-k">ON DELETE</span> <span class="pl-k">SET</span> <span class="pl-k">NULL</span> <span class="pl-k">ON</span> <span class="pl-k">UPDATE</span> CASCADE,
  <span class="pl-c">/* ... */</span>
);</pre>
  </div>
  <h3><a id="user-content-参数-1" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E5%8F%82%E6%95%B0-1" aria-hidden="true"></a>参数</h3>
  <p>在这种情况下要应用的参数与一对一情况相同. 例如,要更改外键的名称并确保该关系是强制性的,我们可以执行以下操作：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Team</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Player</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">foreignKey</span>: <span class="pl-s">'clubId'</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Player</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Team</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>如同一对一关系,&nbsp;<code>ON DELETE</code>&nbsp;默认为&nbsp;<code>SET NULL</code>&nbsp;而&nbsp;<code>ON UPDATE</code>&nbsp;默认为&nbsp;<code>CASCADE</code>.</p>
  <h2><a id="user-content-多对多关系" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E5%A4%9A%E5%AF%B9%E5%A4%9A%E5%85%B3%E7%B3%BB" aria-hidden="true"></a>多对多关系</h2>
  <h3><a id="user-content-原理-1" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E5%8E%9F%E7%90%86-1" aria-hidden="true"></a>原理</h3>
  <p>多对多关联将一个源与多个目标相连,而所有这些目标又可以与第一个目标之外的其他源相连.</p>
  <p>不能像其他关系那样通过向其中一个表添加一个外键来表示这一点. 取而代之的是使用<a href="https://en.wikipedia.org/wiki/Associative_entity" rel="nofollow">联结模型</a>的概念. 这将是一个额外的模型(以及数据库中的额外表),它将具有两个外键列并跟踪关联. 联结表有时也称为&nbsp;<em>join table</em>&nbsp;或&nbsp;<em>through table</em>.</p>
  <h3><a id="user-content-目标-2" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E7%9B%AE%E6%A0%87-2" aria-hidden="true"></a>目标</h3>
  <p>对于此示例,我们将考虑模型&nbsp;<code>Movie</code>&nbsp;和&nbsp;<code>Actor</code>. 一位 actor 可能参与了许多 movies,而一部 movie 中有许多 actors 参与了其制作. 跟踪关联的联结表将被称为&nbsp;<code>ActorMovies</code>,其中将包含外键&nbsp;<code>movieId</code>&nbsp;和&nbsp;<code>actorId</code>.</p>
  <h3><a id="user-content-实践-2" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E5%AE%9E%E8%B7%B5-2" aria-hidden="true"></a>实践</h3>
  <p>在 Sequelize 中执行此操作的主要方法如下：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">Movie</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'Movie'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Actor</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'Actor'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Movie</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Actor</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-s">'ActorMovies'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Actor</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Movie</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-s">'ActorMovies'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>因为在&nbsp;<code>belongsToMany</code>&nbsp;的&nbsp;<code>through</code>&nbsp;参数中给出了一个字符串,所以 Sequelize 将自动创建&nbsp;<code>ActorMovies</code>&nbsp;模型作为联结模型. 例如,在 PostgreSQL 中：</p>
  <div class="highlight highlight-source-sql">
<pre><span class="pl-k">CREATE</span> <span class="pl-k">TABLE</span> <span class="pl-en">IF</span> NOT EXISTS <span class="pl-s"><span class="pl-pds">"</span>ActorMovies<span class="pl-pds">"</span></span> (
  <span class="pl-s"><span class="pl-pds">"</span>createdAt<span class="pl-pds">"</span></span> <span class="pl-k">TIMESTAMP WITH TIME ZONE</span> <span class="pl-k">NOT NULL</span>,
  <span class="pl-s"><span class="pl-pds">"</span>updatedAt<span class="pl-pds">"</span></span> <span class="pl-k">TIMESTAMP WITH TIME ZONE</span> <span class="pl-k">NOT NULL</span>,
  <span class="pl-s"><span class="pl-pds">"</span>MovieId<span class="pl-pds">"</span></span> <span class="pl-k">INTEGER</span> <span class="pl-k">REFERENCES</span> <span class="pl-s"><span class="pl-pds">"</span>Movies<span class="pl-pds">"</span></span> (<span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>) <span class="pl-k">ON DELETE CASCADE</span> <span class="pl-k">ON</span> <span class="pl-k">UPDATE</span> CASCADE,
  <span class="pl-s"><span class="pl-pds">"</span>ActorId<span class="pl-pds">"</span></span> <span class="pl-k">INTEGER</span> <span class="pl-k">REFERENCES</span> <span class="pl-s"><span class="pl-pds">"</span>Actors<span class="pl-pds">"</span></span> (<span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>) <span class="pl-k">ON DELETE CASCADE</span> <span class="pl-k">ON</span> <span class="pl-k">UPDATE</span> CASCADE,
  <span class="pl-k">PRIMARY KEY</span> (<span class="pl-s"><span class="pl-pds">"</span>MovieId<span class="pl-pds">"</span></span>,<span class="pl-s"><span class="pl-pds">"</span>ActorId<span class="pl-pds">"</span></span>)
);</pre>
  </div>
  <p>除了字符串以外,还支持直接传递模型,在这种情况下,给定的模型将用作联结模型(并且不会自动创建任何模型). 例如：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">Movie</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'Movie'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Actor</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'Actor'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">ActorMovies</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'ActorMovies'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">MovieId</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
    <span class="pl-c1">references</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">model</span>: <span class="pl-v">Movie</span><span class="pl-kos">,</span> <span class="pl-c">// 'Movies' 也可以使用</span>
      <span class="pl-c1">key</span>: <span class="pl-s">'id'</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">ActorId</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
    <span class="pl-c1">references</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">model</span>: <span class="pl-v">Actor</span><span class="pl-kos">,</span> <span class="pl-c">// 'Actors' 也可以使用</span>
      <span class="pl-c1">key</span>: <span class="pl-s">'id'</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Movie</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Actor</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-s">'ActorMovies'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Actor</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Movie</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-s">'ActorMovies'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>上面的代码在 PostgreSQL 中产生了以下 SQL,与上面所示的代码等效：</p>
  <div class="highlight highlight-source-sql">
<pre><span class="pl-k">CREATE</span> <span class="pl-k">TABLE</span> <span class="pl-en">IF</span> NOT EXISTS <span class="pl-s"><span class="pl-pds">"</span>ActorMovies<span class="pl-pds">"</span></span> (
  <span class="pl-s"><span class="pl-pds">"</span>MovieId<span class="pl-pds">"</span></span> <span class="pl-k">INTEGER</span> <span class="pl-k">NOT NULL</span> <span class="pl-k">REFERENCES</span> <span class="pl-s"><span class="pl-pds">"</span>Movies<span class="pl-pds">"</span></span> (<span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>) <span class="pl-k">ON DELETE</span> RESTRICT <span class="pl-k">ON</span> <span class="pl-k">UPDATE</span> CASCADE,
  <span class="pl-s"><span class="pl-pds">"</span>ActorId<span class="pl-pds">"</span></span> <span class="pl-k">INTEGER</span> <span class="pl-k">NOT NULL</span> <span class="pl-k">REFERENCES</span> <span class="pl-s"><span class="pl-pds">"</span>Actors<span class="pl-pds">"</span></span> (<span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>) <span class="pl-k">ON DELETE</span> RESTRICT <span class="pl-k">ON</span> <span class="pl-k">UPDATE</span> CASCADE,
  <span class="pl-s"><span class="pl-pds">"</span>createdAt<span class="pl-pds">"</span></span> <span class="pl-k">TIMESTAMP WITH TIME ZONE</span> <span class="pl-k">NOT NULL</span>,
  <span class="pl-s"><span class="pl-pds">"</span>updatedAt<span class="pl-pds">"</span></span> <span class="pl-k">TIMESTAMP WITH TIME ZONE</span> <span class="pl-k">NOT NULL</span>,
  UNIQUE (<span class="pl-s"><span class="pl-pds">"</span>MovieId<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>ActorId<span class="pl-pds">"</span></span>),     <span class="pl-c">-- 注意: Sequelize 产生了这个 UNIQUE 约束,但是</span>
  <span class="pl-k">PRIMARY KEY</span> (<span class="pl-s"><span class="pl-pds">"</span>MovieId<span class="pl-pds">"</span></span>,<span class="pl-s"><span class="pl-pds">"</span>ActorId<span class="pl-pds">"</span></span>)  <span class="pl-c">-- 这没有关系,因为它也是 PRIMARY KEY</span>
);</pre>
  </div>
  <h3><a id="user-content-参数-2" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E5%8F%82%E6%95%B0-2" aria-hidden="true"></a>参数</h3>
  <p>与一对一和一对多关系不同,对于多对多关系,<code>ON UPDATE</code>&nbsp;和&nbsp;<code>ON DELETE</code>&nbsp;的默认值为&nbsp;<code>CASCADE</code>.</p>
  <p>当模型中不存在主键时，Belongs-to-Many 将创建一个唯一键。 可以使用&nbsp;<strong>uniqueKey</strong>&nbsp;参数覆盖此唯一键名.</p>
  <div class="highlight highlight-source-js">
    <pre><span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">User</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-v">UserProjects</span><span class="pl-kos">,</span> <span class="pl-c1">uniqueKey</span>: <span class="pl-s">'my_custom_unique'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span></pre>
  </div>
  <h2><a id="user-content-基本的涉及关联的查询" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E5%9F%BA%E6%9C%AC%E7%9A%84%E6%B6%89%E5%8F%8A%E5%85%B3%E8%81%94%E7%9A%84%E6%9F%A5%E8%AF%A2" aria-hidden="true"></a>基本的涉及关联的查询</h2>
  <p>了解了定义关联的基础知识之后,我们可以查看涉及关联的查询. 最常见查询是&nbsp;<em>read</em>&nbsp;查询(即 SELECT). 稍后,将展示其他类型的查询.</p>
  <p>为了研究这一点,我们将思考一个例子,其中有船和船长,以及它们之间的一对一关系. 我们将在外键上允许 null(默认值),这意味着船可以在没有船长的情况下存在,反之亦然.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 这是我们用于以下示例的模型的设置</span>
<span class="pl-k">const</span> <span class="pl-v">Ship</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'ship'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">crewCapacity</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
  <span class="pl-c1">amountOfSails</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Captain</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'captain'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">skillLevel</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
    <span class="pl-c1">validate</span>: <span class="pl-kos">{</span> <span class="pl-c1">min</span>: <span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">max</span>: <span class="pl-c1">10</span> <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Captain</span><span class="pl-kos">.</span><span class="pl-en">hasOne</span><span class="pl-kos">(</span><span class="pl-v">Ship</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Ship</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Captain</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h3><a id="user-content-获取关联---预先加载-vs-延迟加载" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E8%8E%B7%E5%8F%96%E5%85%B3%E8%81%94---%E9%A2%84%E5%85%88%E5%8A%A0%E8%BD%BD-vs-%E5%BB%B6%E8%BF%9F%E5%8A%A0%E8%BD%BD" aria-hidden="true"></a>获取关联 - 预先加载 vs 延迟加载</h3>
  <p>预先加载和延迟加载的概念是理解获取关联如何在 Sequelize 中工作的基础. 延迟加载是指仅在确实需要时才获取关联数据的技术. 另一方面,预先加载是指从一开始就通过较大的查询一次获取所有内容的技术.</p>
  <h4><a id="user-content-延迟加载示例" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E5%BB%B6%E8%BF%9F%E5%8A%A0%E8%BD%BD%E7%A4%BA%E4%BE%8B" aria-hidden="true"></a>延迟加载示例</h4>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">awesomeCaptain</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Captain</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">name</span>: <span class="pl-s">"Jack Sparrow"</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 用获取到的 captain 做点什么</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">'Name:'</span><span class="pl-kos">,</span> <span class="pl-s1">awesomeCaptain</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">'Skill Level:'</span><span class="pl-kos">,</span> <span class="pl-s1">awesomeCaptain</span><span class="pl-kos">.</span><span class="pl-c1">skillLevel</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 现在我们需要有关他的 ship 的信息!</span>
<span class="pl-k">const</span> <span class="pl-s1">hisShip</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">awesomeCaptain</span><span class="pl-kos">.</span><span class="pl-en">getShip</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 用 ship 做点什么</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">'Ship Name:'</span><span class="pl-kos">,</span> <span class="pl-s1">hisShip</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">'Amount of Sails:'</span><span class="pl-kos">,</span> <span class="pl-s1">hisShip</span><span class="pl-kos">.</span><span class="pl-c1">amountOfSails</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>请注意,在上面的示例中,我们进行了两个查询,仅在要使用它时才获取关联的 ship. 如果我们可能需要也可能不需要这艘 ship,或者我们只想在少数情况下有条件地取回它,这会特别有用; 这样,我们可以仅在必要时提取,从而节省时间和内存.</p>
  <p>注意：上面使用的&nbsp;<code>getShip()</code>&nbsp;实例方法是 Sequelize 自动添加到 Captain 实例的方法之一. 还有其他方法, 你将在本指南的后面部分进一步了解它们.</p>
  <h4><a id="user-content-预先加载示例" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E9%A2%84%E5%85%88%E5%8A%A0%E8%BD%BD%E7%A4%BA%E4%BE%8B" aria-hidden="true"></a>预先加载示例</h4>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">awesomeCaptain</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Captain</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">name</span>: <span class="pl-s">"Jack Sparrow"</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">include</span>: <span class="pl-v">Ship</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 现在 ship 跟着一起来了</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">'Name:'</span><span class="pl-kos">,</span> <span class="pl-s1">awesomeCaptain</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">'Skill Level:'</span><span class="pl-kos">,</span> <span class="pl-s1">awesomeCaptain</span><span class="pl-kos">.</span><span class="pl-c1">skillLevel</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">'Ship Name:'</span><span class="pl-kos">,</span> <span class="pl-s1">awesomeCaptain</span><span class="pl-kos">.</span><span class="pl-c1">ship</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">'Amount of Sails:'</span><span class="pl-kos">,</span> <span class="pl-s1">awesomeCaptain</span><span class="pl-kos">.</span><span class="pl-c1">ship</span><span class="pl-kos">.</span><span class="pl-c1">amountOfSails</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>如上所示,通过使用 include 参数 在 Sequelize 中执行预先加载. 观察到这里只对数据库执行了一个查询(与实例一起带回关联的数据).</p>
  <p>这只是 Sequelize 中预先加载的简单介绍. 还有更多内容,你可以在<a href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/advanced-association-concepts/eager-loading.md">预先加载的专用指南</a>中学习</p>
  <h3><a id="user-content-创建-更新和删除" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E5%88%9B%E5%BB%BA-%E6%9B%B4%E6%96%B0%E5%92%8C%E5%88%A0%E9%99%A4" aria-hidden="true"></a>创建, 更新和删除</h3>
  <p>上面显示了查询有关关联的数据的基础知识. 对于创建,更新和删除,你可以：</p>
  <ul>
    <li>
      <p>直接使用标准模型查询：</p>
      <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 示例：使用标准方法创建关联的模型</span>
<span class="pl-v">Bar</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">name</span>: <span class="pl-s">'My Bar'</span><span class="pl-kos">,</span>
  <span class="pl-c1">fooId</span>: <span class="pl-c1">5</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 这将创建一个属于 ID 5 的 Foo 的 Bar</span>
<span class="pl-c">// 这里没有什么特别的东西</span></pre>
      </div>
    </li>
    <li>
      <p>或使用关联模型可用的&nbsp;<em><a href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/%EF%BC%83special-methods-mixins-to-instances">特殊方法/混合</a></em>&nbsp;,这将在本文稍后进行解释.</p>
    </li>
  </ul>
  <p><strong>注意:</strong>&nbsp;<a href="https://sequelize.org/master/class/lib/model.js~Model.html#instance-method-save" rel="nofollow"><code>save()</code>实例方法</a>&nbsp;并不知道关联关系. 如果你修改了&nbsp;<em>父级</em>&nbsp;对象预先加载的&nbsp;<em>子级</em>&nbsp;的值,那么在父级上调用&nbsp;<code>save()</code>&nbsp;将会忽略子级上发生的修改.</p>
  <h2><a id="user-content-关联别名--自定义外键" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E5%85%B3%E8%81%94%E5%88%AB%E5%90%8D--%E8%87%AA%E5%AE%9A%E4%B9%89%E5%A4%96%E9%94%AE" aria-hidden="true"></a>关联别名 &amp; 自定义外键</h2>
  <p>在以上所有示例中,Sequelize 自动定义了外键名称. 例如,在船和船长示例中,Sequelize 在 Ship 模型上自动定义了一个&nbsp;<code>captainId</code>&nbsp;字段. 然而,想要自定义外键也是很容易的.</p>
  <p>让我们以简化的形式考虑 Ship 和 Captain 模型,仅着眼于当前主题,如下所示(较少的字段)：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">Ship</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'ship'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Captain</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'captain'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>有三种方法可以为外键指定不同的名称：</p>
  <ul>
    <li>通过直接提供外键名称</li>
    <li>通过定义别名</li>
    <li>通过两个方法同时进行</li>
  </ul>
  <h3><a id="user-content-回顾-默认设置" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E5%9B%9E%E9%A1%BE-%E9%BB%98%E8%AE%A4%E8%AE%BE%E7%BD%AE" aria-hidden="true"></a>回顾: 默认设置</h3>
  <p>通过简单地使用&nbsp;<code>Ship.belongsTo(Captain)</code>,sequelize 将自动生成外键名称：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Ship</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Captain</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 这将在 Ship 中创建 `captainId` 外键.</span>

<span class="pl-c">// 通过将模型传递给 `include` 来完成预先加载:</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-v">Ship</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Captain</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toJSON</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 或通过提供关联的模型名称:</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-v">Ship</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-s">'captain'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toJSON</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 同样,实例获得用于延迟加载的 `getCaptain()` 方法：</span>
<span class="pl-k">const</span> <span class="pl-s1">ship</span> <span class="pl-c1">=</span> <span class="pl-v">Ship</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">ship</span><span class="pl-kos">.</span><span class="pl-en">getCaptain</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toJSON</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h3><a id="user-content-直接提供外键名称" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E7%9B%B4%E6%8E%A5%E6%8F%90%E4%BE%9B%E5%A4%96%E9%94%AE%E5%90%8D%E7%A7%B0" aria-hidden="true"></a>直接提供外键名称</h3>
  <p>可以直接在关联定义的参数中提供外键名称,如下所示：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Ship</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Captain</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">foreignKey</span>: <span class="pl-s">'bossId'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 这将在 Ship 中创建 `bossId` 外键.</span>

<span class="pl-c">// 通过将模型传递给 `include` 来完成预先加载:</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-v">Ship</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Captain</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toJSON</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 或通过提供关联的模型名称:</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-v">Ship</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-s">'Captain'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toJSON</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 同样,实例获得用于延迟加载的 `getCaptain()` 方法:</span>
<span class="pl-k">const</span> <span class="pl-s1">ship</span> <span class="pl-c1">=</span> <span class="pl-v">Ship</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">ship</span><span class="pl-kos">.</span><span class="pl-en">getCaptain</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toJSON</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h3><a id="user-content-定义别名" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E5%AE%9A%E4%B9%89%E5%88%AB%E5%90%8D" aria-hidden="true"></a>定义别名</h3>
  <p>定义别名比简单指定外键的自定义名称更强大. 通过一个示例可以更好地理解这一点：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Ship</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Captain</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">as</span>: <span class="pl-s">'leader'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 这将在 Ship 中创建 `leaderId` 外键.</span>

<span class="pl-c">// 通过将模型传递给 `include` 不能再触发预先加载:</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-v">Ship</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Captain</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toJSON</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 引发错误</span>
<span class="pl-c">// 相反,你必须传递别名:</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-v">Ship</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-s">'leader'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toJSON</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 或者,你可以传递一个指定模型和别名的对象:</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-v">Ship</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Captain</span><span class="pl-kos">,</span>
    <span class="pl-c1">as</span>: <span class="pl-s">'leader'</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toJSON</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 同样,实例获得用于延迟加载的 `getLeader()`方法:</span>
<span class="pl-k">const</span> <span class="pl-s1">ship</span> <span class="pl-c1">=</span> <span class="pl-v">Ship</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">ship</span><span class="pl-kos">.</span><span class="pl-en">getLeader</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toJSON</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>当你需要在同一模型之间定义两个不同的关联时,别名特别有用. 例如,如果我们有<code>Mail</code>&nbsp;和&nbsp;<code>Person</code>&nbsp;模型,则可能需要将它们关联两次,以表示邮件的&nbsp;<code>sender</code>&nbsp;和&nbsp;<code>receiver</code>. 在这种情况下,我们必须为每个关联使用别名,因为否则,诸如&nbsp;<code>mail.getPerson()</code>&nbsp;之类的调用将是模棱两可的. 使用&nbsp;<code>sender</code>和&nbsp;<code>receiver</code>&nbsp;别名,我们将有两种可用的可用方法：<code>mail.getSender()</code>&nbsp;和&nbsp;<code>mail.getReceiver()</code>,它们都返回一个<code>Promise&lt;Person&gt;</code>.</p>
  <p>在为&nbsp;<code>hasOne</code>&nbsp;或&nbsp;<code>belongsTo</code>&nbsp;关联定义别名时,应使用单词的单数形式(例如上例中的&nbsp;<code>leader</code>). 另一方面,在为&nbsp;<code>hasMany</code>&nbsp;和&nbsp;<code>belongsToMany</code>&nbsp;定义别名时,应使用复数形式.&nbsp;<a href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/advanced-association-concepts/advanced-many-to-many.md">高级多对多关联指南</a>中介绍了定义多对多关系(带有<code>belongsToMany</code>)的别名.</p>
  <h3><a id="user-content-两者都做" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E4%B8%A4%E8%80%85%E9%83%BD%E5%81%9A" aria-hidden="true"></a>两者都做</h3>
  <p>我们可以定义别名,也可以直接定义外键:</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Ship</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Captain</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">as</span>: <span class="pl-s">'leader'</span><span class="pl-kos">,</span> <span class="pl-c1">foreignKey</span>: <span class="pl-s">'bossId'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 这将在 Ship 中创建 `bossId` 外键.</span>

<span class="pl-c">// 由于定义了别名,因此仅通过将模型传递给 `include`,预先加载将不起作用:</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-v">Ship</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Captain</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toJSON</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 引发错误</span>
<span class="pl-c">// 相反,你必须传递别名:</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-v">Ship</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-s">'leader'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toJSON</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 或者,你可以传递一个指定模型和别名的对象:</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-v">Ship</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Captain</span><span class="pl-kos">,</span>
    <span class="pl-c1">as</span>: <span class="pl-s">'leader'</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toJSON</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 同样,实例获得用于延迟加载的 `getLeader()` 方法:</span>
<span class="pl-k">const</span> <span class="pl-s1">ship</span> <span class="pl-c1">=</span> <span class="pl-v">Ship</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">ship</span><span class="pl-kos">.</span><span class="pl-en">getLeader</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toJSON</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h2><a id="user-content-添加到实例的特殊方法" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E6%B7%BB%E5%8A%A0%E5%88%B0%E5%AE%9E%E4%BE%8B%E7%9A%84%E7%89%B9%E6%AE%8A%E6%96%B9%E6%B3%95" aria-hidden="true"></a>添加到实例的特殊方法</h2>
  <p>当两个模型之间定义了关联时,这些模型的实例将获得特殊的方法来与其关联的另一方进行交互.</p>
  <p>例如,如果我们有两个模型&nbsp;<code>Foo</code>&nbsp;和&nbsp;<code>Bar</code>,并且它们是关联的,则它们的实例将具有以下可用的方法,具体取决于关联类型：</p>
  <h3><a id="user-content-foohasonebar" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#foohasonebar" aria-hidden="true"></a><code>Foo.hasOne(Bar)</code></h3>
  <ul>
    <li><code>fooInstance.getBar()</code></li>
    <li><code>fooInstance.setBar()</code></li>
    <li><code>fooInstance.createBar()</code></li>
  </ul>
  <p>示例:</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">foo</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'the-foo'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">bar1</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Bar</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'some-bar'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">bar2</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Bar</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'another-bar'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">foo</span><span class="pl-kos">.</span><span class="pl-en">getBar</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// null</span>
<span class="pl-k">await</span> <span class="pl-s1">foo</span><span class="pl-kos">.</span><span class="pl-en">setBar</span><span class="pl-kos">(</span><span class="pl-s1">bar1</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">foo</span><span class="pl-kos">.</span><span class="pl-en">getBar</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 'some-bar'</span>
<span class="pl-k">await</span> <span class="pl-s1">foo</span><span class="pl-kos">.</span><span class="pl-en">createBar</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'yet-another-bar'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">newlyAssociatedBar</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">foo</span><span class="pl-kos">.</span><span class="pl-en">getBar</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">newlyAssociatedBar</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 'yet-another-bar'</span>
<span class="pl-k">await</span> <span class="pl-s1">foo</span><span class="pl-kos">.</span><span class="pl-en">setBar</span><span class="pl-kos">(</span><span class="pl-c1">null</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// Un-associate</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">foo</span><span class="pl-kos">.</span><span class="pl-en">getBar</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// null</span></pre>
  </div>
  <h3><a id="user-content-foobelongstobar" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#foobelongstobar" aria-hidden="true"></a><code>Foo.belongsTo(Bar)</code></h3>
  <p>来自&nbsp;<code>Foo.hasOne(Bar)</code>&nbsp;的相同内容:</p>
  <ul>
    <li><code>fooInstance.getBar()</code></li>
    <li><code>fooInstance.setBar()</code></li>
    <li><code>fooInstance.createBar()</code></li>
  </ul>
  <h3><a id="user-content-foohasmanybar" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#foohasmanybar" aria-hidden="true"></a><code>Foo.hasMany(Bar)</code></h3>
  <ul>
    <li><code>fooInstance.getBars()</code></li>
    <li><code>fooInstance.countBars()</code></li>
    <li><code>fooInstance.hasBar()</code></li>
    <li><code>fooInstance.hasBars()</code></li>
    <li><code>fooInstance.setBars()</code></li>
    <li><code>fooInstance.addBar()</code></li>
    <li><code>fooInstance.addBars()</code></li>
    <li><code>fooInstance.removeBar()</code></li>
    <li><code>fooInstance.removeBars()</code></li>
    <li><code>fooInstance.createBar()</code></li>
  </ul>
  <p>示例:</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">foo</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'the-foo'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">bar1</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Bar</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'some-bar'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">bar2</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Bar</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'another-bar'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">foo</span><span class="pl-kos">.</span><span class="pl-en">getBars</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// []</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">foo</span><span class="pl-kos">.</span><span class="pl-en">countBars</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 0</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">foo</span><span class="pl-kos">.</span><span class="pl-en">hasBar</span><span class="pl-kos">(</span><span class="pl-s1">bar1</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// false</span>
<span class="pl-k">await</span> <span class="pl-s1">foo</span><span class="pl-kos">.</span><span class="pl-en">addBars</span><span class="pl-kos">(</span><span class="pl-kos">[</span><span class="pl-s1">bar1</span><span class="pl-kos">,</span> <span class="pl-s1">bar2</span><span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">foo</span><span class="pl-kos">.</span><span class="pl-en">countBars</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 2</span>
<span class="pl-k">await</span> <span class="pl-s1">foo</span><span class="pl-kos">.</span><span class="pl-en">addBar</span><span class="pl-kos">(</span><span class="pl-s1">bar1</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">foo</span><span class="pl-kos">.</span><span class="pl-en">countBars</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 2</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">foo</span><span class="pl-kos">.</span><span class="pl-en">hasBar</span><span class="pl-kos">(</span><span class="pl-s1">bar1</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// true</span>
<span class="pl-k">await</span> <span class="pl-s1">foo</span><span class="pl-kos">.</span><span class="pl-en">removeBar</span><span class="pl-kos">(</span><span class="pl-s1">bar2</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">foo</span><span class="pl-kos">.</span><span class="pl-en">countBars</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 1</span>
<span class="pl-k">await</span> <span class="pl-s1">foo</span><span class="pl-kos">.</span><span class="pl-en">createBar</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'yet-another-bar'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">foo</span><span class="pl-kos">.</span><span class="pl-en">countBars</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 2</span>
<span class="pl-k">await</span> <span class="pl-s1">foo</span><span class="pl-kos">.</span><span class="pl-en">setBars</span><span class="pl-kos">(</span><span class="pl-kos">[</span><span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 取消关联所有先前关联的 Bars</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">foo</span><span class="pl-kos">.</span><span class="pl-en">countBars</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 0</span></pre>
  </div>
  <p>getter 方法接受参数,就像通常的 finder 方法(例如<code>findAll</code>)一样：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">easyTasks</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">project</span><span class="pl-kos">.</span><span class="pl-en">getTasks</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">difficulty</span>: <span class="pl-kos">{</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">lte</span><span class="pl-kos">]</span>: <span class="pl-c1">5</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">taskTitles</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">project</span><span class="pl-kos">.</span><span class="pl-en">getTasks</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">attributes</span>: <span class="pl-kos">[</span><span class="pl-s">'title'</span><span class="pl-kos">]</span><span class="pl-kos">,</span>
  <span class="pl-c1">raw</span>: <span class="pl-c1">true</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">map</span><span class="pl-kos">(</span><span class="pl-s1">task</span> <span class="pl-c1">=&gt;</span> <span class="pl-s1">task</span><span class="pl-kos">.</span><span class="pl-c1">title</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h3><a id="user-content-foobelongstomanybar--through-baz-" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#foobelongstomanybar--through-baz-" aria-hidden="true"></a><code>Foo.belongsToMany(Bar, { through: Baz })</code></h3>
  <p>来自&nbsp;<code>Foo.hasMany(Bar)</code>&nbsp;的相同内容:</p>
  <ul>
    <li><code>fooInstance.getBars()</code></li>
    <li><code>fooInstance.countBars()</code></li>
    <li><code>fooInstance.hasBar()</code></li>
    <li><code>fooInstance.hasBars()</code></li>
    <li><code>fooInstance.setBars()</code></li>
    <li><code>fooInstance.addBar()</code></li>
    <li><code>fooInstance.addBars()</code></li>
    <li><code>fooInstance.removeBar()</code></li>
    <li><code>fooInstance.removeBars()</code></li>
    <li><code>fooInstance.createBar()</code></li>
  </ul>
  <h3><a id="user-content-注意-方法名称" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E6%B3%A8%E6%84%8F-%E6%96%B9%E6%B3%95%E5%90%8D%E7%A7%B0" aria-hidden="true"></a>注意: 方法名称</h3>
  <p>如上面的示例所示,Sequelize 赋予这些特殊方法的名称是由前缀(例如,get,add,set)和模型名称(首字母大写)组成的. 必要时,可以使用复数形式,例如在&nbsp;<code>fooInstance.setBars()</code>&nbsp;中. 同样,不规则复数也由 Sequelize 自动处理. 例如,<code>Person</code>&nbsp;变成&nbsp;<code>People</code>&nbsp;或者&nbsp;<code>Hypothesis</code>&nbsp;变成&nbsp;<code>Hypotheses</code>.</p>
  <p>如果定义了别名,则将使用别名代替模型名称来形成方法名称. 例如：</p>
  <div class="highlight highlight-source-js">
    <pre><span class="pl-v">Task</span><span class="pl-kos">.</span><span class="pl-en">hasOne</span><span class="pl-kos">(</span><span class="pl-v">User</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">as</span>: <span class="pl-s">'Author'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <ul>
    <li><code>taskInstance.getAuthor()</code></li>
    <li><code>taskInstance.setAuthor()</code></li>
    <li><code>taskInstance.createAuthor()</code></li>
  </ul>
  <h2><a id="user-content-为什么关联是成对定义的" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E4%B8%BA%E4%BB%80%E4%B9%88%E5%85%B3%E8%81%94%E6%98%AF%E6%88%90%E5%AF%B9%E5%AE%9A%E4%B9%89%E7%9A%84" aria-hidden="true"></a>为什么关联是成对定义的？</h2>
  <p>如前所述,就像上面大多数示例中展示的,Sequelize 中的关联通常成对定义：</p>
  <ul>
    <li>创建一个&nbsp;<strong>一对一</strong>&nbsp;关系,&nbsp;<code>hasOne</code>&nbsp;和&nbsp;<code>belongsTo</code>&nbsp;关联一起使用;</li>
    <li>创建一个&nbsp;<strong>一对多</strong>&nbsp;关系,&nbsp;<code>hasMany</code>&nbsp;he&nbsp;<code>belongsTo</code>&nbsp;关联一起使用;</li>
    <li>创建一个&nbsp;<strong>多对多</strong>&nbsp;关系, 两个&nbsp;<code>belongsToMany</code>&nbsp;调用一起使用.</li>
  </ul>
  <p>当在两个模型之间定义了 Sequelize 关联时,只有&nbsp;<em>源</em>&nbsp;模型&nbsp;<em>知晓关系</em>. 因此,例如,当使用&nbsp;<code>Foo.hasOne(Bar)</code>(当前,<code>Foo</code>&nbsp;是源模型,而&nbsp;<code>Bar</code>&nbsp;是目标模型)时,只有&nbsp;<code>Foo</code>&nbsp;知道该关联的存在. 这就是为什么在这种情况下,如上所示,<code>Foo</code>&nbsp;实例获得方法&nbsp;<code>getBar()</code>,&nbsp;<code>setBar()</code>&nbsp;和&nbsp;<code>createBar()</code>&nbsp;而另一方面,<code>Bar</code>&nbsp;实例却没有获得任何方法.</p>
  <p>类似地,对于&nbsp;<code>Foo.hasOne(Bar)</code>,由于&nbsp;<code>Foo</code>&nbsp;了解这种关系,我们可以像&nbsp;<code>Foo.findOne({ include: Bar })</code>&nbsp;中那样执行预先加载,但不能执行&nbsp;<code>Bar.findOne({ include: Foo })</code>.</p>
  <p>因此,为了充分发挥 Sequelize 的作用,我们通常成对设置关系,以便两个模型都&nbsp;<em>互相知晓</em>.</p>
  <p>实际示范:</p>
  <ul>
    <li>
      <p>如果我们未定义关联对,则仅调用&nbsp;<code>Foo.hasOne(Bar)</code>:</p>
      <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 这有效...</span>
<span class="pl-k">await</span> <span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Bar</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 但这会引发错误:</span>
<span class="pl-k">await</span> <span class="pl-v">Bar</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Foo</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// SequelizeEagerLoadingError: foo is not associated to bar!</span></pre>
      </div>
    </li>
    <li>
      <p>如果我们按照建议定义关联对, 即,&nbsp;<code>Foo.hasOne(Bar)</code>&nbsp;和&nbsp;<code>Bar.belongsTo(Foo)</code>:</p>
      <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 这有效</span>
<span class="pl-k">await</span> <span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Bar</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 这也有效!</span>
<span class="pl-k">await</span> <span class="pl-v">Bar</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Foo</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
      </div>
    </li>
  </ul>
  <h2><a id="user-content-涉及相同模型的多个关联" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E6%B6%89%E5%8F%8A%E7%9B%B8%E5%90%8C%E6%A8%A1%E5%9E%8B%E7%9A%84%E5%A4%9A%E4%B8%AA%E5%85%B3%E8%81%94" aria-hidden="true"></a>涉及相同模型的多个关联</h2>
  <p>在 Sequelize 中,可以在同一模型之间定义多个关联. 你只需要为它们定义不同的别名：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Team</span><span class="pl-kos">.</span><span class="pl-en">hasOne</span><span class="pl-kos">(</span><span class="pl-v">Game</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">as</span>: <span class="pl-s">'HomeTeam'</span><span class="pl-kos">,</span> <span class="pl-c1">foreignKey</span>: <span class="pl-s">'homeTeamId'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Team</span><span class="pl-kos">.</span><span class="pl-en">hasOne</span><span class="pl-kos">(</span><span class="pl-v">Game</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">as</span>: <span class="pl-s">'AwayTeam'</span><span class="pl-kos">,</span> <span class="pl-c1">foreignKey</span>: <span class="pl-s">'awayTeamId'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Game</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Team</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h2><a id="user-content-创建引用非主键字段的关联" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E5%88%9B%E5%BB%BA%E5%BC%95%E7%94%A8%E9%9D%9E%E4%B8%BB%E9%94%AE%E5%AD%97%E6%AE%B5%E7%9A%84%E5%85%B3%E8%81%94" aria-hidden="true"></a>创建引用非主键字段的关联</h2>
  <p>在以上所有示例中,通过引用所涉及模型的主键(在我们的示例中为它们的ID)定义了关联. 但是,Sequelize 允许你定义一个关联,该关联使用另一个字段而不是主键字段来建立关联.</p>
  <p>此其他字段必须对此具有唯一的约束(否则,这将没有意义).</p>
  <h3><a id="user-content-对于-belongsto-关系" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E5%AF%B9%E4%BA%8E-belongsto-%E5%85%B3%E7%B3%BB" aria-hidden="true"></a>对于&nbsp;<code>belongsTo</code>&nbsp;关系</h3>
  <p>首先,回想一下&nbsp;<code>A.belongsTo(B)</code>&nbsp;关联将外键放在&nbsp;<em>源模型</em>&nbsp;中(即,在&nbsp;<code>A</code>&nbsp;中).</p>
  <p>让我们再次使用"船和船长"的示例. 此外,我们将假定船长姓名是唯一的：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">Ship</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'ship'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Captain</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'captain'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">name</span>: <span class="pl-kos">{</span> <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span> <span class="pl-c1">unique</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>这样,我们不用在 Ship 上保留&nbsp;<code>captainId</code>,而是可以保留&nbsp;<code>captainName</code>&nbsp;并将其用作关联跟踪器. 换句话说,我们的关系将引用目标模型上的另一列：<code>name</code>&nbsp;列,而不是从目标模型(Captain)中引用&nbsp;<code>id</code>. 为了说明这一点,我们必须定义一个&nbsp;<em>目标键</em>. 我们还必须为外键本身指定一个名称：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Ship</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Captain</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">targetKey</span>: <span class="pl-s">'name'</span><span class="pl-kos">,</span> <span class="pl-c1">foreignKey</span>: <span class="pl-s">'captainName'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 这将在源模型(Ship)中创建一个名为 `captainName` 的外键,</span>
<span class="pl-c">// 该外键引用目标模型(Captain)中的 `name` 字段.</span></pre>
  </div>
  <p>现在我们可以做类似的事情:</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">await</span> <span class="pl-v">Captain</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">"Jack Sparrow"</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">ship</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Ship</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">"Black Pearl"</span><span class="pl-kos">,</span> <span class="pl-c1">captainName</span>: <span class="pl-s">"Jack Sparrow"</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">ship</span><span class="pl-kos">.</span><span class="pl-en">getCaptain</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// "Jack Sparrow"</span></pre>
  </div>
  <h3><a id="user-content-对于-hasone-和-hasmany-关系" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E5%AF%B9%E4%BA%8E-hasone-%E5%92%8C-hasmany-%E5%85%B3%E7%B3%BB" aria-hidden="true"></a>对于&nbsp;<code>hasOne</code>&nbsp;和&nbsp;<code>hasMany</code>&nbsp;关系</h3>
  <p>可以将完全相同的想法应用于&nbsp;<code>hasOne</code>&nbsp;和&nbsp;<code>hasMany</code>&nbsp;关联,但是在定义关联时,我们提供了&nbsp;<code>sourceKey</code>,而不是提供&nbsp;<code>targetKey</code>. 这是因为与&nbsp;<code>belongsTo</code>&nbsp;不同,<code>hasOne</code>&nbsp;和&nbsp;<code>hasMany</code>关联将外键保留在目标模型上：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">Foo</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'foo'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">name</span>: <span class="pl-kos">{</span> <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span> <span class="pl-c1">unique</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Bar</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'bar'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">title</span>: <span class="pl-kos">{</span> <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span> <span class="pl-c1">unique</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Baz</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'baz'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">summary</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">hasOne</span><span class="pl-kos">(</span><span class="pl-v">Bar</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">sourceKey</span>: <span class="pl-s">'name'</span><span class="pl-kos">,</span> <span class="pl-c1">foreignKey</span>: <span class="pl-s">'fooName'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Bar</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Baz</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">sourceKey</span>: <span class="pl-s">'title'</span><span class="pl-kos">,</span> <span class="pl-c1">foreignKey</span>: <span class="pl-s">'barTitle'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// [...]</span>
<span class="pl-k">await</span> <span class="pl-v">Bar</span><span class="pl-kos">.</span><span class="pl-en">setFoo</span><span class="pl-kos">(</span><span class="pl-s">"Foo's Name Here"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">await</span> <span class="pl-v">Baz</span><span class="pl-kos">.</span><span class="pl-en">addBar</span><span class="pl-kos">(</span><span class="pl-s">"Bar's Title Here"</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h3><a id="user-content-对于-belongstomany-关系" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E5%AF%B9%E4%BA%8E-belongstomany-%E5%85%B3%E7%B3%BB" aria-hidden="true"></a>对于&nbsp;<code>belongsToMany</code>&nbsp;关系</h3>
  <p>同样的想法也可以应用于&nbsp;<code>belongsToMany</code>&nbsp;关系. 但是,与其他情况下(其中只涉及一个外键)不同,<code>belongsToMany</code>&nbsp;关系涉及两个外键,这些外键保留在额外的表(联结表)上.</p>
  <p>请考虑以下设置：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">Foo</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'foo'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">name</span>: <span class="pl-kos">{</span> <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span> <span class="pl-c1">unique</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Bar</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'bar'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">title</span>: <span class="pl-kos">{</span> <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span> <span class="pl-c1">unique</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>有四种情况需要考虑：</p>
  <ul>
    <li>我们可能希望使用默认的主键为&nbsp;<code>Foo</code>&nbsp;和&nbsp;<code>Bar</code>&nbsp;进行多对多关系：</li>
  </ul>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Bar</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-s">'foo_bar'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 这将创建具有字段 `fooId` 和 `barID` 的联结表 `foo_bar`.</span></pre>
  </div>
  <ul>
    <li>我们可能希望使用默认主键&nbsp;<code>Foo</code>&nbsp;的多对多关系,但使用&nbsp;<code>Bar</code>&nbsp;的不同字段：</li>
  </ul>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Bar</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-s">'foo_bar'</span><span class="pl-kos">,</span> <span class="pl-c1">targetKey</span>: <span class="pl-s">'title'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 这将创建具有字段 `fooId` 和 `barTitle` 的联结表 `foo_bar`.</span></pre>
  </div>
  <ul>
    <li>我们可能希望使用&nbsp;<code>Foo</code>&nbsp;的不同字段和&nbsp;<code>Bar</code>&nbsp;的默认主键进行多对多关系：</li>
  </ul>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Bar</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-s">'foo_bar'</span><span class="pl-kos">,</span> <span class="pl-c1">sourceKey</span>: <span class="pl-s">'name'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 这将创建具有字段 `fooName` 和 `barId` 的联结表 `foo_bar`.</span></pre>
  </div>
  <ul>
    <li>我们可能希望使用不同的字段为&nbsp;<code>Foo</code>&nbsp;和&nbsp;<code>Bar</code>&nbsp;使用多对多关系：</li>
  </ul>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Bar</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-s">'foo_bar'</span><span class="pl-kos">,</span> <span class="pl-c1">sourceKey</span>: <span class="pl-s">'name'</span><span class="pl-kos">,</span> <span class="pl-c1">targetKey</span>: <span class="pl-s">'title'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 这将创建带有字段 `fooName` 和 `barTitle` 的联结表 `foo_bar`.</span></pre>
  </div>
  <h3><a id="user-content-注意" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/assocs.md#%E6%B3%A8%E6%84%8F" aria-hidden="true"></a>注意</h3>
  <p>不要忘记关联中引用的字段必须具有唯一性约束. 否则,将引发错误(对于 SQLite 有时还会发出诡异的错误消息,例如&nbsp;<code>SequelizeDatabaseError: SQLITE_ERROR: foreign key mismatch - "ships" referencing "captains"</code>).</p>
  <p>在&nbsp;<code>sourceKey</code>&nbsp;和&nbsp;<code>targetKey</code>&nbsp;之间做出决定的技巧只是记住每个关系在何处放置其外键. 如本指南开头所述：</p>
  <ul>
    <li>
      <p><code>A.belongsTo(B)</code>&nbsp;将外键保留在源模型中(<code>A</code>),因此引用的键在目标模型中,因此使用了&nbsp;<code>targetKey</code>.</p>
    </li>
    <li>
      <p><code>A.hasOne(B)</code>&nbsp;和&nbsp;<code>A.hasMany(B)</code>&nbsp;将外键保留在目标模型(<code>B</code>)中,因此引用的键在源模型中,因此使用了&nbsp;<code>sourceKey</code>.</p>
    </li>
    <li>
      <p><code>A.belongsToMany(B)</code>&nbsp;包含一个额外的表(联结表),因此&nbsp;<code>sourceKey</code>&nbsp;和&nbsp;<code>targetKey</code>&nbsp;均可用,其中&nbsp;<code>sourceKey</code>&nbsp;对应于<code>A</code>(源)中的某个字段而&nbsp;<code>targetKey</code>&nbsp;对应于&nbsp;<code>B</code>(目标)中的某个字段.</p>
    </li>
  </ul>
  <pre><span class="pl-kos"><br /><br /></span></pre>
  <h1>Paranoid - 偏执表</h1>
  <p>Sequelize 支持&nbsp;<em>paranoid</em>&nbsp;表的概念. 一个&nbsp;<em>paranoid</em>&nbsp;表是一个被告知删除记录时不会真正删除它的表.反而一个名为&nbsp;<code>deletedAt</code>&nbsp;的特殊列会将其值设置为该删除请求的时间戳.</p>
  <p>这意味着偏执表会执行记录的&nbsp;<em>软删除</em>,而不是&nbsp;<em>硬删除</em>.</p>
  <h2><a id="user-content-将模型定义为-paranoid" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/paranoid.md#%E5%B0%86%E6%A8%A1%E5%9E%8B%E5%AE%9A%E4%B9%89%E4%B8%BA-paranoid" aria-hidden="true"></a>将模型定义为 paranoid</h2>
  <p>要定义 paranoid 模型,必须将&nbsp;<code>paranoid: true</code>&nbsp;参数传递给模型定义. Paranoid 需要时间戳才能起作用(即,如果你传递&nbsp;<code>timestamps: false</code>了,paranoid 将不起作用).</p>
  <p>你还可以将默认的列名(默认是&nbsp;<code>deletedAt</code>)更改为其他名称.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">class</span> <span class="pl-v">Post</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c">/* 这是属性 */</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  sequelize<span class="pl-kos">,</span>
  <span class="pl-c1">paranoid</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>

  <span class="pl-c">// 如果要为 deletedAt 列指定自定义名称</span>
  <span class="pl-c1">deletedAt</span>: <span class="pl-s">'destroyTime'</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h2><a id="user-content-删除" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/paranoid.md#%E5%88%A0%E9%99%A4" aria-hidden="true"></a>删除</h2>
  <p>当你调用&nbsp;<code>destroy</code>&nbsp;方法时,将发生软删除：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">await</span> <span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">destroy</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">id</span>: <span class="pl-c1">1</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// UPDATE "posts" SET "deletedAt"=[timestamp] WHERE "deletedAt" IS NULL AND "id" = 1</span></pre>
  </div>
  <p>如果你确实想要硬删除,并且模型是 paranoid,则可以使用&nbsp;<code>force: true</code>&nbsp;参数强制执行：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">await</span> <span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">destroy</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">id</span>: <span class="pl-c1">1</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">force</span>: <span class="pl-c1">true</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// DELETE FROM "posts" WHERE "id" = 1</span></pre>
  </div>
  <p>上面的示例以静态的&nbsp;<code>destroy</code>&nbsp;方法为例(<code>Post.destroy</code>),所有实例方法的工作方式相同：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">post</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">title</span>: <span class="pl-s">'test'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">post</span> <span class="pl-k">instanceof</span> <span class="pl-v">Post</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// true</span>
<span class="pl-k">await</span> <span class="pl-s1">post</span><span class="pl-kos">.</span><span class="pl-en">destroy</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 只设置 `deletedAt` 标志</span>
<span class="pl-k">await</span> <span class="pl-s1">post</span><span class="pl-kos">.</span><span class="pl-en">destroy</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">force</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 真的会删除记录</span></pre>
  </div>
  <h2><a id="user-content-恢复" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/paranoid.md#%E6%81%A2%E5%A4%8D" aria-hidden="true"></a>恢复</h2>
  <p>要恢复软删除的记录,可以使用&nbsp;<code>restore</code>&nbsp;方法,该方法在静态版本和实例版本中都提供：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 展示实例 `restore` 方法的示例</span>
<span class="pl-c">// 我们创建一个帖子,对其进行软删除,然后将其还原</span>
<span class="pl-k">const</span> <span class="pl-s1">post</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">title</span>: <span class="pl-s">'test'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">post</span> <span class="pl-k">instanceof</span> <span class="pl-v">Post</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// true</span>
<span class="pl-k">await</span> <span class="pl-s1">post</span><span class="pl-kos">.</span><span class="pl-en">destroy</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">'soft-deleted!'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">await</span> <span class="pl-s1">post</span><span class="pl-kos">.</span><span class="pl-en">restore</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">'restored!'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 展示静态 `restore` 方法的示例.</span>
<span class="pl-c">// 恢复每个 likes 大于 100 的软删除的帖子</span>
<span class="pl-k">await</span> <span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">restore</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">likes</span>: <span class="pl-kos">{</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">gt</span><span class="pl-kos">]</span>: <span class="pl-c1">100</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h2><a id="user-content-其他查询行为" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/paranoid.md#%E5%85%B6%E4%BB%96%E6%9F%A5%E8%AF%A2%E8%A1%8C%E4%B8%BA" aria-hidden="true"></a>其他查询行为</h2>
  <p>Sequelize 执行的每个查询将自动忽略软删除的记录(当然,原始查询除外).</p>
  <p>这意味着,例如,<code>findAll</code>&nbsp;方法将看不到软删除的记录,仅获取未删除的记录.</p>
  <p>即使你单纯的调用提供了软删除记录主键的<code>findByPk</code>,结果也将是&nbsp;<code>null</code>,就好像该记录不存在一样.</p>
  <p>如果你真的想让查询看到被软删除的记录,可以将&nbsp;<code>paranoid: false</code>&nbsp;参数传递给查询方法. 例如：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">await</span> <span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">findByPk</span><span class="pl-kos">(</span><span class="pl-c1">123</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 如果 ID 123 的记录被软删除,则将返回 `null`</span>
<span class="pl-k">await</span> <span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">findByPk</span><span class="pl-kos">(</span><span class="pl-c1">123</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">paranoid</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 这将检索记录</span>

<span class="pl-k">await</span> <span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span> <span class="pl-c1">foo</span>: <span class="pl-s">'bar'</span> <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 这将不会检索软删除的记录</span>

<span class="pl-k">await</span> <span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span> <span class="pl-c1">foo</span>: <span class="pl-s">'bar'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">paranoid</span>: <span class="pl-c1">false</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 这还将检索软删除的记录</span></pre>
  </div>
  <pre>&nbsp;</pre>
</div>

<div class="l-title">高级关联概念</div>
<h1>Eager Loading - 预先加载</h1>
<p>如<a href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/core-concepts/assocs.md">关联指南</a>中简要提到的,预先加载是一次查询多个模型(一个"主"模型和一个或多个关联模型)的数据的行为. 在 SQL 级别上,这是具有一个或多个&nbsp;<a href="https://en.wikipedia.org/wiki/Join_(SQL)" rel="nofollow">join</a>&nbsp;的查询.</p>
<p>完成此操作后,Sequelize 将在返回的对象中将适当关联的模型添加到适当命名的自动创建的字段中.</p>
<p>在 Sequelize 中,主要通过在模型查找器查询中使用&nbsp;<code>include</code>&nbsp;参数(例如,<code>findOne</code>,&nbsp;<code>findAll</code>&nbsp;等)来完成预先加载.</p>
<h2><a id="user-content-基本示例" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/eager-loading.md#%E5%9F%BA%E6%9C%AC%E7%A4%BA%E4%BE%8B" aria-hidden="true"></a>基本示例</h2>
<p>让我们假设以下设置：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">User</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'user'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Task</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'task'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Tool</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'tool'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">size</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Task</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Task</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">User</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Tool</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">as</span>: <span class="pl-s">'Instruments'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h3><a id="user-content-获取单个关联元素" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/eager-loading.md#%E8%8E%B7%E5%8F%96%E5%8D%95%E4%B8%AA%E5%85%B3%E8%81%94%E5%85%83%E7%B4%A0" aria-hidden="true"></a>获取单个关联元素</h3>
<p>首先,让我们用其关联的用户加载所有任务：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">tasks</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Task</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">User</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-c1">JSON</span><span class="pl-kos">.</span><span class="pl-en">stringify</span><span class="pl-kos">(</span><span class="pl-s1">tasks</span><span class="pl-kos">,</span> <span class="pl-c1">null</span><span class="pl-kos">,</span> <span class="pl-c1">2</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>输出:</p>
<div class="highlight highlight-source-json">
<pre>[{
  <span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>A Task<span class="pl-pds">"</span></span>,
  <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>,
  <span class="pl-s"><span class="pl-pds">"</span>userId<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>,
  <span class="pl-s"><span class="pl-pds">"</span>user<span class="pl-pds">"</span></span>: {
    <span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>John Doe<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>
  }
}]</pre>
</div>
<p>这里,<code>tasks[0].user instanceof User</code>&nbsp;是&nbsp;<code>true</code>. 这表明,当 Sequelize 提取关联的模型时,它们将作为模型实例添加到输出对象.</p>
<p>上面,在获取的任务中,关联的模型被添加到名为&nbsp;<code>user</code>&nbsp;的新字段中. Sequelize 会根据关联模型的名称自动选择此字段的名称,在适用的情况下(即关联为&nbsp;<code>hasMany</code>&nbsp;或&nbsp;<code>belongsToMany</code>)使用该字段的复数形式. 换句话说,由于<code>Task.belongsTo(User)</code>导致一项任务与一个用户相关联,因此逻辑选择是单数形式(Sequelize 自动遵循该形式).</p>
<h3><a id="user-content-获取所有关联的元素" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/eager-loading.md#%E8%8E%B7%E5%8F%96%E6%89%80%E6%9C%89%E5%85%B3%E8%81%94%E7%9A%84%E5%85%83%E7%B4%A0" aria-hidden="true"></a>获取所有关联的元素</h3>
<p>现在,我们将执行相反的操作,而不是加载与给定任务关联的用户,我们将找到与给定用户关联的所有任务.</p>
<p>方法调用本质上是相同的. 唯一的区别是,现在在查询结果中创建的额外字段使用复数形式(在这种情况下为&nbsp;<code>tasks</code>),其值是任务实例的数组(而不是上面的单个实例).</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">users</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Task</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-c1">JSON</span><span class="pl-kos">.</span><span class="pl-en">stringify</span><span class="pl-kos">(</span><span class="pl-s1">users</span><span class="pl-kos">,</span> <span class="pl-c1">null</span><span class="pl-kos">,</span> <span class="pl-c1">2</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>输出:</p>
<div class="highlight highlight-source-json">
<pre>[{
  <span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>John Doe<span class="pl-pds">"</span></span>,
  <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>,
  <span class="pl-s"><span class="pl-pds">"</span>tasks<span class="pl-pds">"</span></span>: [{
    <span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>A Task<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>,
    <span class="pl-s"><span class="pl-pds">"</span>userId<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>
  }]
}]</pre>
</div>
<p>注意,由于关联是一对多的,因此访问器(结果实例中的<code>tasks</code>属性)是复数的.</p>
<h3><a id="user-content-获取别名关联" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/eager-loading.md#%E8%8E%B7%E5%8F%96%E5%88%AB%E5%90%8D%E5%85%B3%E8%81%94" aria-hidden="true"></a>获取别名关联</h3>
<p>如果关联是别名的(使用<code>as</code>参数),则在包含模型时必须指定此别名. 与其直接将模型传递给&nbsp;<code>include</code>&nbsp;参数,不如为对象提供两个选项：<code>model</code>&nbsp;和&nbsp;<code>as</code>.</p>
<p>注意上面的用户的&nbsp;<code>Tool</code>&nbsp;是如何被别名为&nbsp;<code>Instruments</code>&nbsp;的. 为了实现这一点,你必须指定要加载的模型以及别名：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">users</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">{</span> <span class="pl-c1">model</span>: <span class="pl-v">Tool</span><span class="pl-kos">,</span> <span class="pl-c1">as</span>: <span class="pl-s">'Instruments'</span> <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-c1">JSON</span><span class="pl-kos">.</span><span class="pl-en">stringify</span><span class="pl-kos">(</span><span class="pl-s1">users</span><span class="pl-kos">,</span> <span class="pl-c1">null</span><span class="pl-kos">,</span> <span class="pl-c1">2</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>Output:</p>
<div class="highlight highlight-source-json">
<pre>[{
  <span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>John Doe<span class="pl-pds">"</span></span>,
  <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>,
  <span class="pl-s"><span class="pl-pds">"</span>Instruments<span class="pl-pds">"</span></span>: [{
    <span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>Scissor<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>,
    <span class="pl-s"><span class="pl-pds">"</span>userId<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>
  }]
}]</pre>
</div>
<p>你也可以包括指定的关联别名相匹配的字符串：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-s">'Instruments'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 也可以正常使用</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-kos">{</span> <span class="pl-c1">association</span>: <span class="pl-s">'Instruments'</span> <span class="pl-kos">}</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 也可以正常使用</span></pre>
</div>
<h3><a id="user-content-需要预先加载" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/eager-loading.md#%E9%9C%80%E8%A6%81%E9%A2%84%E5%85%88%E5%8A%A0%E8%BD%BD" aria-hidden="true"></a>需要预先加载</h3>
<p>预先加载时,我们可以强制查询仅返回具有关联模型的记录,从而有效地将查询从默认的&nbsp;<code>OUTER JOIN</code>&nbsp;转为&nbsp;<code>INNER JOIN</code>. 这是通过&nbsp;<code>required: true</code>参数完成的,如下所示：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Task</span><span class="pl-kos">,</span>
    <span class="pl-c1">required</span>: <span class="pl-c1">true</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>此参数也适用于嵌套包含.</p>
<h3><a id="user-content-在模型级别的预先加载过滤" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/eager-loading.md#%E5%9C%A8%E6%A8%A1%E5%9E%8B%E7%BA%A7%E5%88%AB%E7%9A%84%E9%A2%84%E5%85%88%E5%8A%A0%E8%BD%BD%E8%BF%87%E6%BB%A4" aria-hidden="true"></a>在模型级别的预先加载过滤</h3>
<p>预先加载时,我们还可以使用&nbsp;<code>where</code>&nbsp;参数过滤关联的模型,如以下示例所示：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Tool</span><span class="pl-kos">,</span>
    <span class="pl-c1">as</span>: <span class="pl-s">'Instruments'</span>
    <span class="pl-s1">where</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">size</span>: <span class="pl-kos">{</span>
        <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">ne</span><span class="pl-kos">]</span>: <span class="pl-s">'small'</span>
      <span class="pl-kos">}</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>生成 SQL:</p>
<div class="highlight highlight-source-sql">
<pre><span class="pl-k">SELECT</span>
  <span class="pl-s"><span class="pl-pds">`</span>user<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>user<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>name<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments.id<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>name<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments.name<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>size<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments.size<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>userId<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments.userId<span class="pl-pds">`</span></span>
<span class="pl-k">FROM</span> <span class="pl-s"><span class="pl-pds">`</span>users<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>user<span class="pl-pds">`</span></span>
<span class="pl-k">INNER JOIN</span> <span class="pl-s"><span class="pl-pds">`</span>tools<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span> <span class="pl-k">ON</span>
  <span class="pl-s"><span class="pl-pds">`</span>user<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>userId<span class="pl-pds">`</span></span> <span class="pl-k">AND</span>
  <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>size<span class="pl-pds">`</span></span> <span class="pl-k">!=</span> <span class="pl-s"><span class="pl-pds">'</span>small<span class="pl-pds">'</span></span>;</pre>
</div>
<p>请注意,上面生成的 SQL 查询将仅获取具有至少一个符合条件(在这种情况下为&nbsp;<code>small</code>)的工具的用户. 出现这种情况是因为,当在&nbsp;<code>include</code>&nbsp;内使用&nbsp;<code>where</code>&nbsp;参数时,Sequelize 会自动将&nbsp;<code>required</code>&nbsp;参数设置为&nbsp;<code>true</code>. 这意味着,将执行&nbsp;<code>INNER JOIN</code>&nbsp;而不是&nbsp;<code>OUTER JOIN</code>,仅返回具有至少一个匹配子代的父代模型.</p>
<p>还要注意,使用的&nbsp;<code>where</code>&nbsp;参数已转换为&nbsp;<code>INNER JOIN</code>&nbsp;的&nbsp;<code>ON</code>&nbsp;子句的条件. 为了获得&nbsp;<em>顶层</em>&nbsp;的&nbsp;<code>WHERE</code>&nbsp;子句,而不是&nbsp;<code>ON</code>&nbsp;子句,必须做一些不同的事情.接下来将展示.</p>
<h4><a id="user-content-参考其他列" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/eager-loading.md#%E5%8F%82%E8%80%83%E5%85%B6%E4%BB%96%E5%88%97" aria-hidden="true"></a>参考其他列</h4>
<p>如果你想在包含模型中应用&nbsp;<code>WHERE</code>&nbsp;子句来引用关联模型中的值,则可以简单地使用&nbsp;<code>Sequelize.col</code>&nbsp;函数,如以下示例所示：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-c">// 查找所有具有至少一项任务的项目,其中 task.state === project.state</span>
<span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Task</span><span class="pl-kos">,</span>
    <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">state</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-en">col</span><span class="pl-kos">(</span><span class="pl-s">'project.state'</span><span class="pl-kos">)</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span></pre>
</div>
<h3><a id="user-content-顶层的复杂-where-子句" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/eager-loading.md#%E9%A1%B6%E5%B1%82%E7%9A%84%E5%A4%8D%E6%9D%82-where-%E5%AD%90%E5%8F%A5" aria-hidden="true"></a>顶层的复杂 where 子句</h3>
<p>为了获得涉及嵌套列的顶级&nbsp;<code>WHERE</code>&nbsp;子句,Sequelize 提供了一种引用嵌套列的方法：<code>'$nested.column$'</code>&nbsp;语法.</p>
<p>例如,它可以用于将&nbsp;<code>where</code>&nbsp;条件从包含的模型从&nbsp;<code>ON</code>&nbsp;条件移动到顶层的&nbsp;<code>WHERE</code>&nbsp;子句.</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-s">'$Instruments.size$'</span>: <span class="pl-kos">{</span> <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">ne</span><span class="pl-kos">]</span>: <span class="pl-s">'small'</span> <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Tool</span><span class="pl-kos">,</span>
    <span class="pl-c1">as</span>: <span class="pl-s">'Instruments'</span>
  <span class="pl-kos">}</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>生成 SQL:</p>
<div class="highlight highlight-source-sql">
<pre><span class="pl-k">SELECT</span>
  <span class="pl-s"><span class="pl-pds">`</span>user<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>user<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>name<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments.id<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>name<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments.name<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>size<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments.size<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>userId<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments.userId<span class="pl-pds">`</span></span>
<span class="pl-k">FROM</span> <span class="pl-s"><span class="pl-pds">`</span>users<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>user<span class="pl-pds">`</span></span>
<span class="pl-k">LEFT OUTER JOIN</span> <span class="pl-s"><span class="pl-pds">`</span>tools<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span> <span class="pl-k">ON</span>
  <span class="pl-s"><span class="pl-pds">`</span>user<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>userId<span class="pl-pds">`</span></span>
<span class="pl-k">WHERE</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>size<span class="pl-pds">`</span></span> <span class="pl-k">!=</span> <span class="pl-s"><span class="pl-pds">'</span>small<span class="pl-pds">'</span></span>;</pre>
</div>
<p><code>$nested.column$</code>&nbsp;语法也适用于嵌套了多个级别的列,例如&nbsp;<code>$some.super.deeply.nested.column$</code>. 因此,你可以使用它对深层嵌套的列进行复杂的过滤.</p>
<p>为了更好地理解内部的&nbsp;<code>where</code>&nbsp;参数(在&nbsp;<code>include</code>&nbsp;内部使用)和使用与不使用&nbsp;<code>required</code>&nbsp;参数与使用&nbsp;<code>$nested.column$</code>&nbsp;语法的顶级&nbsp;<code>where</code>&nbsp;之间的所有区别. ,下面我们为你提供四个示例：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-c">// Inner where, 默认使用 `required: true`</span>
<span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Tool</span><span class="pl-kos">,</span>
    <span class="pl-c1">as</span>: <span class="pl-s">'Instruments'</span><span class="pl-kos">,</span>
    <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">size</span>: <span class="pl-kos">{</span> <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">ne</span><span class="pl-kos">]</span>: <span class="pl-s">'small'</span> <span class="pl-kos">}</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// Inner where, `required: false`</span>
<span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Tool</span><span class="pl-kos">,</span>
    <span class="pl-c1">as</span>: <span class="pl-s">'Instruments'</span><span class="pl-kos">,</span>
    <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">size</span>: <span class="pl-kos">{</span> <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">ne</span><span class="pl-kos">]</span>: <span class="pl-s">'small'</span> <span class="pl-kos">}</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-c1">required</span>: <span class="pl-c1">false</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 顶级 where, 默认使用 `required: false`</span>
<span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-s">'$Instruments.size$'</span>: <span class="pl-kos">{</span> <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">ne</span><span class="pl-kos">]</span>: <span class="pl-s">'small'</span> <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Tool</span><span class="pl-kos">,</span>
    <span class="pl-c1">as</span>: <span class="pl-s">'Instruments'</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 顶级 where, `required: true`</span>
<span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-s">'$Instruments.size$'</span>: <span class="pl-kos">{</span> <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">ne</span><span class="pl-kos">]</span>: <span class="pl-s">'small'</span> <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Tool</span><span class="pl-kos">,</span>
    <span class="pl-c1">as</span>: <span class="pl-s">'Instruments'</span><span class="pl-kos">,</span>
    <span class="pl-c1">required</span>: <span class="pl-c1">true</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>生成 SQL:</p>
<div class="highlight highlight-source-sql">
<pre><span class="pl-c">-- Inner where, 默认使用 `required: true`</span>
<span class="pl-k">SELECT</span> [...] <span class="pl-k">FROM</span> <span class="pl-s"><span class="pl-pds">`</span>users<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>user<span class="pl-pds">`</span></span>
<span class="pl-k">INNER JOIN</span> <span class="pl-s"><span class="pl-pds">`</span>tools<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span> <span class="pl-k">ON</span>
  <span class="pl-s"><span class="pl-pds">`</span>user<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>userId<span class="pl-pds">`</span></span>
  <span class="pl-k">AND</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>size<span class="pl-pds">`</span></span> <span class="pl-k">!=</span> <span class="pl-s"><span class="pl-pds">'</span>small<span class="pl-pds">'</span></span>;

<span class="pl-c">-- Inner where, `required: false`</span>
<span class="pl-k">SELECT</span> [...] <span class="pl-k">FROM</span> <span class="pl-s"><span class="pl-pds">`</span>users<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>user<span class="pl-pds">`</span></span>
<span class="pl-k">LEFT OUTER JOIN</span> <span class="pl-s"><span class="pl-pds">`</span>tools<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span> <span class="pl-k">ON</span>
  <span class="pl-s"><span class="pl-pds">`</span>user<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>userId<span class="pl-pds">`</span></span>
  <span class="pl-k">AND</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>size<span class="pl-pds">`</span></span> <span class="pl-k">!=</span> <span class="pl-s"><span class="pl-pds">'</span>small<span class="pl-pds">'</span></span>;

<span class="pl-c">-- 顶级 where, 默认使用 `required: false`</span>
<span class="pl-k">SELECT</span> [...] <span class="pl-k">FROM</span> <span class="pl-s"><span class="pl-pds">`</span>users<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>user<span class="pl-pds">`</span></span>
<span class="pl-k">LEFT OUTER JOIN</span> <span class="pl-s"><span class="pl-pds">`</span>tools<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span> <span class="pl-k">ON</span>
  <span class="pl-s"><span class="pl-pds">`</span>user<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>userId<span class="pl-pds">`</span></span>
<span class="pl-k">WHERE</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>size<span class="pl-pds">`</span></span> <span class="pl-k">!=</span> <span class="pl-s"><span class="pl-pds">'</span>small<span class="pl-pds">'</span></span>;

<span class="pl-c">-- 顶级 where, `required: true`</span>
<span class="pl-k">SELECT</span> [...] <span class="pl-k">FROM</span> <span class="pl-s"><span class="pl-pds">`</span>users<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>user<span class="pl-pds">`</span></span>
<span class="pl-k">INNER JOIN</span> <span class="pl-s"><span class="pl-pds">`</span>tools<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span> <span class="pl-k">ON</span>
  <span class="pl-s"><span class="pl-pds">`</span>user<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>userId<span class="pl-pds">`</span></span>
<span class="pl-k">WHERE</span> <span class="pl-s"><span class="pl-pds">`</span>Instruments<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>size<span class="pl-pds">`</span></span> <span class="pl-k">!=</span> <span class="pl-s"><span class="pl-pds">'</span>small<span class="pl-pds">'</span></span>;</pre>
</div>
<h3><a id="user-content-使用-right-outer-join-获取-仅限-mysql-mariadb-postgresql-和-mssql" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/eager-loading.md#%E4%BD%BF%E7%94%A8-right-outer-join-%E8%8E%B7%E5%8F%96-%E4%BB%85%E9%99%90-mysql-mariadb-postgresql-%E5%92%8C-mssql" aria-hidden="true"></a>使用&nbsp;<code>RIGHT OUTER JOIN</code>&nbsp;获取 (仅限 MySQL, MariaDB, PostgreSQL 和 MSSQL)</h3>
<p>默认情况下,关联是使用&nbsp;<code>LEFT OUTER JOIN</code>&nbsp;加载的 - 也就是说,它仅包含来自父表的记录. 如果你使用的方言支持,你可以通过传递&nbsp;<code>right</code>&nbsp;选项来将此行为更改为&nbsp;<code>RIGHT OUTER JOIN</code>.</p>
<p>当前, SQLite 不支持&nbsp;<a href="https://www.sqlite.org/omitted.html" rel="nofollow">right joins</a>.</p>
<p><em>注意:</em>&nbsp;仅当&nbsp;<code>required</code>&nbsp;为 false 时才遵循&nbsp;<code>right</code>.</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Task</span> <span class="pl-c">// 将创建一个 left join</span>
  <span class="pl-kos">}</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Task</span><span class="pl-kos">,</span>
    <span class="pl-c1">right</span>: <span class="pl-c1">true</span> <span class="pl-c">// 将创建一个 right join</span>
  <span class="pl-kos">}</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Task</span><span class="pl-kos">,</span>
    <span class="pl-c1">required</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
    <span class="pl-c1">right</span>: <span class="pl-c1">true</span> <span class="pl-c">// 没有效果, 将创建一个 inner join</span>
  <span class="pl-kos">}</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Task</span><span class="pl-kos">,</span>
    <span class="pl-c1">where</span>: <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-kos">{</span> <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">ne</span><span class="pl-kos">]</span>: <span class="pl-s">'empty trash'</span> <span class="pl-kos">}</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-c1">right</span>: <span class="pl-c1">true</span> <span class="pl-c">// 没有效果, 将创建一个 inner join</span>
  <span class="pl-kos">}</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Tool</span><span class="pl-kos">,</span>
    <span class="pl-c1">where</span>: <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-kos">{</span> <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">ne</span><span class="pl-kos">]</span>: <span class="pl-s">'empty trash'</span> <span class="pl-kos">}</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-c1">required</span>: <span class="pl-c1">false</span> <span class="pl-c">// 将创建一个 left join</span>
  <span class="pl-kos">}</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Tool</span><span class="pl-kos">,</span>
    <span class="pl-c1">where</span>: <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-kos">{</span> <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">ne</span><span class="pl-kos">]</span>: <span class="pl-s">'empty trash'</span> <span class="pl-kos">}</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-c1">required</span>: <span class="pl-c1">false</span>
    <span class="pl-s1">right</span>: <span class="pl-c1">true</span> <span class="pl-c">// 将创建一个 right join</span>
  <span class="pl-kos">}</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h2><a id="user-content-多次预先加载" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/eager-loading.md#%E5%A4%9A%E6%AC%A1%E9%A2%84%E5%85%88%E5%8A%A0%E8%BD%BD" aria-hidden="true"></a>多次预先加载</h2>
<p><code>include</code>&nbsp;参数可以接收一个数组,以便一次获取多个关联的模型：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span>
      <span class="pl-c1">model</span>: <span class="pl-v">Bar</span><span class="pl-kos">,</span>
      <span class="pl-c1">required</span>: <span class="pl-c1">true</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">{</span>
      <span class="pl-c1">model</span>: <span class="pl-v">Baz</span><span class="pl-kos">,</span>
      <span class="pl-c1">where</span>: <span class="pl-c">/* ... */</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-v">Qux</span> <span class="pl-c">// { model: Qux } 的简写语法在这里也适用</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span></pre>
</div>
<h2><a id="user-content-多对多关系的预先加载" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/eager-loading.md#%E5%A4%9A%E5%AF%B9%E5%A4%9A%E5%85%B3%E7%B3%BB%E7%9A%84%E9%A2%84%E5%85%88%E5%8A%A0%E8%BD%BD" aria-hidden="true"></a>多对多关系的预先加载</h2>
<p>当你对具有 "多对多" 关系的模型执行预先加载时,默认情况下,Sequelize 也将获取联结表数据. 例如：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">Foo</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'Foo'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">TEXT</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Bar</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'Bar'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">TEXT</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Bar</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-s">'Foo_Bar'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Bar</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Foo</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-s">'Foo_Bar'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">sync</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">foo</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'foo'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">bar</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Bar</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'bar'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">await</span> <span class="pl-s1">foo</span><span class="pl-kos">.</span><span class="pl-en">addBar</span><span class="pl-kos">(</span><span class="pl-s1">bar</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">fetchedFoo</span> <span class="pl-c1">=</span> <span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Bar</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-c1">JSON</span><span class="pl-kos">.</span><span class="pl-en">stringify</span><span class="pl-kos">(</span><span class="pl-s1">fetchedFoo</span><span class="pl-kos">,</span> <span class="pl-c1">null</span><span class="pl-kos">,</span> <span class="pl-c1">2</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>输出:</p>
<div class="highlight highlight-source-json">
<pre>{
  <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>,
  <span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>foo<span class="pl-pds">"</span></span>,
  <span class="pl-s"><span class="pl-pds">"</span>Bars<span class="pl-pds">"</span></span>: [
    {
      <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>,
      <span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>bar<span class="pl-pds">"</span></span>,
      <span class="pl-s"><span class="pl-pds">"</span>Foo_Bar<span class="pl-pds">"</span></span>: {
        <span class="pl-s"><span class="pl-pds">"</span>FooId<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>,
        <span class="pl-s"><span class="pl-pds">"</span>BarId<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>
      }
    }
  ]
}</pre>
</div>
<p>请注意,每个预先加载到&nbsp;<code>Bars</code>&nbsp;属性中的 bar 实例都有一个名为&nbsp;<code>Foo_Bar</code>&nbsp;的额外属性,它是联结模型的相关 Sequelize 实例. 默认情况下,Sequelize 从联结表中获取所有属性,以构建此额外属性.</p>
<p>然而,你可以指定要获取的属性. 这是通过在包含的&nbsp;<code>through</code>&nbsp;参数中应用&nbsp;<code>attributes</code>&nbsp;参数来完成的. 例如：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Bar</span><span class="pl-kos">,</span>
    <span class="pl-c1">through</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">attributes</span>: <span class="pl-kos">[</span><span class="pl-c">/* 在此处列出所需的属性 */</span><span class="pl-kos">]</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>如果你不需要联结表中的任何内容,则可以显式地为&nbsp;<code>attributes</code>&nbsp;参数提供一个空数组,在这种情况下,将不会获取任何内容,甚至不会创建额外的属性：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Bar</span><span class="pl-kos">,</span>
    <span class="pl-c1">attributes</span>: <span class="pl-kos">[</span><span class="pl-kos">]</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>输出:</p>
<div class="highlight highlight-source-json">
<pre>{
  <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>,
  <span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>foo<span class="pl-pds">"</span></span>,
  <span class="pl-s"><span class="pl-pds">"</span>Bars<span class="pl-pds">"</span></span>: [
    {
      <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>,
      <span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>bar<span class="pl-pds">"</span></span>
    }
  ]
}</pre>
</div>
<p>每当包含 "多对多" 关系中的模型时,也可以在联结表上应用过滤器. 这是通过在&nbsp;<code>include</code>&nbsp;的&nbsp;<code>through</code>&nbsp;参数中应用&nbsp;<code>where</code>&nbsp;参数来完成的. 例如：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Project</span><span class="pl-kos">,</span>
    <span class="pl-c1">through</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
        <span class="pl-c">// 这里,`completed` 是联结表上的一列</span>
        <span class="pl-c1">completed</span>: <span class="pl-c1">true</span>
      <span class="pl-kos">}</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>生成 SQL (使用 SQLite):</p>
<div class="highlight highlight-source-sql">
<pre><span class="pl-k">SELECT</span>
  <span class="pl-s"><span class="pl-pds">`</span>User<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>User<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>name<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>Projects<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>Projects.id<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>Projects<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>name<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>Projects.name<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>Projects-&gt;User_Project<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>completed<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>Projects.User_Project.completed<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>Projects-&gt;User_Project<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>UserId<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>Projects.User_Project.UserId<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>Projects-&gt;User_Project<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>ProjectId<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>Projects.User_Project.ProjectId<span class="pl-pds">`</span></span>
<span class="pl-k">FROM</span> <span class="pl-s"><span class="pl-pds">`</span>Users<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>User<span class="pl-pds">`</span></span>
<span class="pl-k">LEFT OUTER JOIN</span> <span class="pl-s"><span class="pl-pds">`</span>User_Projects<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>Projects-&gt;User_Project<span class="pl-pds">`</span></span> <span class="pl-k">ON</span>
  <span class="pl-s"><span class="pl-pds">`</span>User<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">`</span>Projects-&gt;User_Project<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>UserId<span class="pl-pds">`</span></span>
<span class="pl-k">LEFT OUTER JOIN</span> <span class="pl-s"><span class="pl-pds">`</span>Projects<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>Projects<span class="pl-pds">`</span></span> <span class="pl-k">ON</span>
  <span class="pl-s"><span class="pl-pds">`</span>Projects<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">`</span>Projects-&gt;User_Project<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>ProjectId<span class="pl-pds">`</span></span> <span class="pl-k">AND</span>
  <span class="pl-s"><span class="pl-pds">`</span>Projects-&gt;User_Project<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>completed<span class="pl-pds">`</span></span> <span class="pl-k">=</span> <span class="pl-c1">1</span>;</pre>
</div>
<h2><a id="user-content-包括一切" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/eager-loading.md#%E5%8C%85%E6%8B%AC%E4%B8%80%E5%88%87" aria-hidden="true"></a>包括一切</h2>
<p>要包括所有关联的模型,可以使用&nbsp;<code>all</code>&nbsp;和&nbsp;<code>nested</code>&nbsp;参数：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-c">// 提取与用户关联的所有模型</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-kos">{</span> <span class="pl-c1">all</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 递归获取与用户及其嵌套关联关联的所有模型</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-kos">{</span> <span class="pl-c1">all</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span> <span class="pl-c1">nested</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h2><a id="user-content-包括软删除的记录" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/eager-loading.md#%E5%8C%85%E6%8B%AC%E8%BD%AF%E5%88%A0%E9%99%A4%E7%9A%84%E8%AE%B0%E5%BD%95" aria-hidden="true"></a>包括软删除的记录</h2>
<p>如果你想加载软删除的记录,可以通过将&nbsp;<code>include.paranoid</code>&nbsp;设置为&nbsp;<code>false</code>&nbsp;来实现：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Tool</span><span class="pl-kos">,</span>
    <span class="pl-c1">as</span>: <span class="pl-s">'Instruments'</span><span class="pl-kos">,</span>
    <span class="pl-c1">where</span>: <span class="pl-kos">{</span> <span class="pl-c1">size</span>: <span class="pl-kos">{</span> <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">ne</span><span class="pl-kos">]</span>: <span class="pl-s">'small'</span> <span class="pl-kos">}</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-c1">paranoid</span>: <span class="pl-c1">false</span>
  <span class="pl-kos">}</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h2><a id="user-content-排序预先加载的关联" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/eager-loading.md#%E6%8E%92%E5%BA%8F%E9%A2%84%E5%85%88%E5%8A%A0%E8%BD%BD%E7%9A%84%E5%85%B3%E8%81%94" aria-hidden="true"></a>排序预先加载的关联</h2>
<p>当你想将&nbsp;<code>ORDER</code>&nbsp;子句应用于预先加载的模型时,必须对扩展数组使用顶层&nbsp;<code>order</code>&nbsp;参数,从要排序的嵌套模型开始.</p>
<p>通过示例可以更好地理解这一点.</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-v">Company</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-v">Division</span><span class="pl-kos">,</span>
  <span class="pl-c1">order</span>: <span class="pl-kos">[</span>
    <span class="pl-c">// 我们从要排序的模型开始排序数组</span>
    <span class="pl-kos">[</span><span class="pl-v">Division</span><span class="pl-kos">,</span> <span class="pl-s">'name'</span><span class="pl-kos">,</span> <span class="pl-s">'ASC'</span><span class="pl-kos">]</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Company</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-v">Division</span><span class="pl-kos">,</span>
  <span class="pl-c1">order</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">[</span><span class="pl-v">Division</span><span class="pl-kos">,</span> <span class="pl-s">'name'</span><span class="pl-kos">,</span> <span class="pl-s">'DESC'</span><span class="pl-kos">]</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Company</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c">// 如果包含使用别名...</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">{</span> <span class="pl-c1">model</span>: <span class="pl-v">Division</span><span class="pl-kos">,</span> <span class="pl-c1">as</span>: <span class="pl-s">'Div'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">order</span>: <span class="pl-kos">[</span>
    <span class="pl-c">// ...我们在排序数组的开头使用来自 `include` 的相同语法</span>
    <span class="pl-kos">[</span><span class="pl-kos">{</span> <span class="pl-c1">model</span>: <span class="pl-v">Division</span><span class="pl-kos">,</span> <span class="pl-c1">as</span>: <span class="pl-s">'Div'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-s">'name'</span><span class="pl-kos">,</span> <span class="pl-s">'DESC'</span><span class="pl-kos">]</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-v">Company</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c">// 如果我们包含嵌套在多个级别中...</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Division</span><span class="pl-kos">,</span>
    <span class="pl-c1">include</span>: <span class="pl-v">Department</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">order</span>: <span class="pl-kos">[</span>
    <span class="pl-c">// ... 我们在排序数组的开头复制需要的 include 链</span>
    <span class="pl-kos">[</span><span class="pl-v">Division</span><span class="pl-kos">,</span> <span class="pl-v">Department</span><span class="pl-kos">,</span> <span class="pl-s">'name'</span><span class="pl-kos">,</span> <span class="pl-s">'DESC'</span><span class="pl-kos">]</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>对于多对多关系,你还可以按联结表中的属性进行排序.例如,假设我们在&nbsp;<code>Division</code>&nbsp;和&nbsp;<code>Department</code>&nbsp;之间存在多对多关系,联结模型为&nbsp;<code>DepartmentDivision</code>, 你可以这样:</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-v">Company</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Division</span><span class="pl-kos">,</span>
    <span class="pl-c1">include</span>: <span class="pl-v">Department</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">order</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">[</span><span class="pl-v">Division</span><span class="pl-kos">,</span> <span class="pl-v">DepartmentDivision</span><span class="pl-kos">,</span> <span class="pl-s">'name'</span><span class="pl-kos">,</span> <span class="pl-s">'ASC'</span><span class="pl-kos">]</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>在以上所有示例中,你已经注意到在顶层使用了&nbsp;<code>order</code>&nbsp;参数. 但是在<code>separate: true</code>&nbsp;时,<code>order</code>&nbsp;也可以在&nbsp;<code>include</code>&nbsp;参数中使用. 在这种情况下,用法如下：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-c">// 这仅能用于 `separate: true` (反过来仅适用于 HasMany 关系).</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Post</span><span class="pl-kos">,</span>
    <span class="pl-c1">separate</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
    <span class="pl-c1">order</span>: <span class="pl-kos">[</span>
      <span class="pl-kos">[</span><span class="pl-s">'createdAt'</span><span class="pl-kos">,</span> <span class="pl-s">'DESC'</span><span class="pl-kos">]</span>
    <span class="pl-kos">]</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h3><a id="user-content-涉及子查询的复杂排序" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/eager-loading.md#%E6%B6%89%E5%8F%8A%E5%AD%90%E6%9F%A5%E8%AF%A2%E7%9A%84%E5%A4%8D%E6%9D%82%E6%8E%92%E5%BA%8F" aria-hidden="true"></a>涉及子查询的复杂排序</h3>
<p>查看<a href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/other-topics/sub-queries.md">子查询指南</a>上的示例,了解如何使用子查询来协助更复杂的排序.</p>
<h2><a id="user-content-嵌套的预先加载" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/eager-loading.md#%E5%B5%8C%E5%A5%97%E7%9A%84%E9%A2%84%E5%85%88%E5%8A%A0%E8%BD%BD" aria-hidden="true"></a>嵌套的预先加载</h2>
<p>你可以使用嵌套的预先加载来加载相关模型的所有相关模型：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">users</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Tool</span><span class="pl-kos">,</span>
    <span class="pl-c1">as</span>: <span class="pl-s">'Instruments'</span><span class="pl-kos">,</span>
    <span class="pl-c1">include</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">model</span>: <span class="pl-v">Teacher</span><span class="pl-kos">,</span>
      <span class="pl-c1">include</span>: <span class="pl-kos">[</span> <span class="pl-c">/* ... */</span> <span class="pl-kos">]</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-c1">JSON</span><span class="pl-kos">.</span><span class="pl-en">stringify</span><span class="pl-kos">(</span><span class="pl-s1">users</span><span class="pl-kos">,</span> <span class="pl-c1">null</span><span class="pl-kos">,</span> <span class="pl-c1">2</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>输出:</p>
<div class="highlight highlight-source-json">
<pre>[{
  <span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>John Doe<span class="pl-pds">"</span></span>,
  <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>,
  <span class="pl-s"><span class="pl-pds">"</span>Instruments<span class="pl-pds">"</span></span>: [{ <span class="pl-ii">//</span> <span class="pl-ii">1</span>:<span class="pl-ii">M</span> <span class="pl-ii">和</span> <span class="pl-ii">N:M</span> <span class="pl-ii">关联</span>
    <span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span><span class="pl-ii">:</span> <span class="pl-s"><span class="pl-pds">"</span>Scissor<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>,
    <span class="pl-s"><span class="pl-pds">"</span>userId<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>,
    <span class="pl-s"><span class="pl-pds">"</span>Teacher<span class="pl-pds">"</span></span>: { <span class="pl-ii">//</span> <span class="pl-ii">1</span>:<span class="pl-c1">1</span> <span class="pl-ii">关联</span>
      <span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span><span class="pl-ii">:</span> <span class="pl-s"><span class="pl-pds">"</span>Jimi Hendrix<span class="pl-pds">"</span></span>
    }
  }]
}]</pre>
</div>
<p>这将产生一个外部连接. 但是,相关模型上的&nbsp;<code>where</code>&nbsp;子句将创建内部联接,并且仅返回具有匹配子模型的实例. 要返回所有父实例,你应该添加&nbsp;<code>required: false</code>.</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Tool</span><span class="pl-kos">,</span>
    <span class="pl-c1">as</span>: <span class="pl-s">'Instruments'</span><span class="pl-kos">,</span>
    <span class="pl-c1">include</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span>
      <span class="pl-c1">model</span>: <span class="pl-v">Teacher</span><span class="pl-kos">,</span>
      <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
        <span class="pl-c1">school</span>: <span class="pl-s">"Woodstock Music School"</span>
      <span class="pl-kos">}</span><span class="pl-kos">,</span>
      <span class="pl-c1">required</span>: <span class="pl-c1">false</span>
    <span class="pl-kos">}</span><span class="pl-kos">]</span>
  <span class="pl-kos">}</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>上面的查询将返回所有用户及其所有乐器,但仅返回与&nbsp;<code>Woodstock Music School</code>&nbsp;相关的那些老师.</p>
<h2><a id="user-content-使用带有-include-的-findandcountall" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/eager-loading.md#%E4%BD%BF%E7%94%A8%E5%B8%A6%E6%9C%89-include-%E7%9A%84-findandcountall" aria-hidden="true"></a>使用带有 include 的&nbsp;<code>findAndCountAll</code></h2>
<p><code>findAndCountAll</code>&nbsp;实用功能支持 include. 仅将标记为&nbsp;<code>required</code>&nbsp;的 include 项视为&nbsp;<code>count</code>. 例如,如果你要查找并统计所有拥有个人资料的用户：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAndCountAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span> <span class="pl-c1">model</span>: <span class="pl-v">Profile</span><span class="pl-kos">,</span> <span class="pl-c1">required</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span>
  <span class="pl-kos">]</span><span class="pl-kos">,</span>
  <span class="pl-c1">limit</span>: <span class="pl-c1">3</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>因为&nbsp;<code>Profile</code>&nbsp;的 include 已设置为&nbsp;<code>required</code>,它将导致内部联接,并且仅统计具有个人资料的用户. 如果我们从包含中删除&nbsp;<code>required</code>,则包含和不包含配置文件的用户都将被计数. 在 include 中添加一个&nbsp;<code>where</code>&nbsp;子句会自动使它成为 required：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAndCountAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span> <span class="pl-c1">model</span>: <span class="pl-v">Profile</span><span class="pl-kos">,</span> <span class="pl-c1">where</span>: <span class="pl-kos">{</span> <span class="pl-c1">active</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span> <span class="pl-kos">}</span>
  <span class="pl-kos">]</span><span class="pl-kos">,</span>
  <span class="pl-c1">limit</span>: <span class="pl-c1">3</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>上面的查询仅会统计拥有有效个人资料的用户,因为当你在&nbsp;<code>include</code>&nbsp;中添加&nbsp;<code>where</code>&nbsp;子句时,<code>required</code>&nbsp;会隐式设置为&nbsp;<code>true</code>.</p>
<p>&nbsp;</p>
<h1>Creating with Associations - 创建关联</h1>
<p>只要所有元素都是新元素,就可以一步创建带有嵌套关联的实例.</p>
<p>相反,无法执行涉及嵌套对象的更新和删除. 为此,你将必须明确执行每个单独的操作.</p>
<h2><a id="user-content-belongsto--hasmany--hasone-关联" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/creating-with-associations.md#belongsto--hasmany--hasone-%E5%85%B3%E8%81%94" aria-hidden="true"></a>BelongsTo / HasMany / HasOne 关联</h2>
<p>考虑以下模型:</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">class</span> <span class="pl-v">Product</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">Product</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">title</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> sequelize<span class="pl-kos">,</span> <span class="pl-c1">modelName</span>: <span class="pl-s">'product'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">class</span> <span class="pl-v">User</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">firstName</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">lastName</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> sequelize<span class="pl-kos">,</span> <span class="pl-c1">modelName</span>: <span class="pl-s">'user'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">class</span> <span class="pl-v">Address</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">Address</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">line1</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">line2</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">city</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">state</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">zip</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> sequelize<span class="pl-kos">,</span> <span class="pl-c1">modelName</span>: <span class="pl-s">'address'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 我们保存关联设置调用的返回值,以便以后使用</span>
<span class="pl-v">Product</span><span class="pl-kos">.</span><span class="pl-c1">User</span> <span class="pl-c1">=</span> <span class="pl-v">Product</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">User</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-c1">Addresses</span> <span class="pl-c1">=</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Address</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 也适用于 `hasOne`</span></pre>
</div>
<p>一个新的&nbsp;<code>Product</code>,<code>User</code>&nbsp;和一个或多个&nbsp;<code>Address</code>&nbsp;可以按以下步骤一步创建：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">return</span> <span class="pl-v">Product</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">title</span>: <span class="pl-s">'Chair'</span><span class="pl-kos">,</span>
  <span class="pl-c1">user</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">firstName</span>: <span class="pl-s">'Mick'</span><span class="pl-kos">,</span>
    <span class="pl-c1">lastName</span>: <span class="pl-s">'Broadstone'</span><span class="pl-kos">,</span>
    <span class="pl-c1">addresses</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span>
      <span class="pl-c1">type</span>: <span class="pl-s">'home'</span><span class="pl-kos">,</span>
      <span class="pl-c1">line1</span>: <span class="pl-s">'100 Main St.'</span><span class="pl-kos">,</span>
      <span class="pl-c1">city</span>: <span class="pl-s">'Austin'</span><span class="pl-kos">,</span>
      <span class="pl-c1">state</span>: <span class="pl-s">'TX'</span><span class="pl-kos">,</span>
      <span class="pl-c1">zip</span>: <span class="pl-s">'78704'</span>
    <span class="pl-kos">}</span><span class="pl-kos">]</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span>
    <span class="pl-c1">association</span>: <span class="pl-v">Product</span><span class="pl-kos">.</span><span class="pl-c1">User</span><span class="pl-kos">,</span>
    <span class="pl-c1">include</span>: <span class="pl-kos">[</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-c1">Addresses</span> <span class="pl-kos">]</span>
  <span class="pl-kos">}</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>观察&nbsp;<code>Product.create</code>&nbsp;调用中&nbsp;<code>include</code>&nbsp;参数的用法. 这对于 Sequelize 理解与关联一起创建的内容很有必要.</p>
<p>注意：这里,我们的用户模型称为<code>user</code>,小写的<code>u</code>-这意味着对象中的属性也应为<code>user</code>. 如果给<code>sequelize.define</code>的名称是<code>User</code>,则对象中的 key 也应该是<code>User</code>. 对于&nbsp;<code>addresses</code>&nbsp;也是如此,除了它是&nbsp;<code>hasMany</code>&nbsp;关联的复数形式.</p>
<h2><a id="user-content-一个别名-belongsto-关联" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/creating-with-associations.md#%E4%B8%80%E4%B8%AA%E5%88%AB%E5%90%8D-belongsto-%E5%85%B3%E8%81%94" aria-hidden="true"></a>一个别名 BelongsTo 关联</h2>
<p>可以扩展前面的示例以支持关联别名.</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">Creator</span> <span class="pl-c1">=</span> <span class="pl-v">Product</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">User</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">as</span>: <span class="pl-s">'creator'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">return</span> <span class="pl-v">Product</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">title</span>: <span class="pl-s">'Chair'</span><span class="pl-kos">,</span>
  <span class="pl-c1">creator</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">firstName</span>: <span class="pl-s">'Matt'</span><span class="pl-kos">,</span>
    <span class="pl-c1">lastName</span>: <span class="pl-s">'Hansen'</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span> <span class="pl-v">Creator</span> <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h2><a id="user-content-hasmany--belongstomany-关联" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/creating-with-associations.md#hasmany--belongstomany-%E5%85%B3%E8%81%94" aria-hidden="true"></a>HasMany / BelongsToMany 关联</h2>
<p>让我们介绍将产品与许多标签关联的功能. 设置模型如下所示：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">class</span> <span class="pl-v">Tag</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">Tag</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">name</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> sequelize<span class="pl-kos">,</span> <span class="pl-c1">modelName</span>: <span class="pl-s">'tag'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-v">Product</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Tag</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 也适用于 `belongsToMany`.</span></pre>
</div>
<p>现在,我们可以通过以下方式创建具有多个标签的产品：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-v">Product</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">id</span>: <span class="pl-c1">1</span><span class="pl-kos">,</span>
  <span class="pl-c1">title</span>: <span class="pl-s">'Chair'</span><span class="pl-kos">,</span>
  <span class="pl-c1">tags</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'Alpha'</span><span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'Beta'</span><span class="pl-kos">}</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span> <span class="pl-v">Tag</span> <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span></pre>
</div>
<p>并且,我们可以修改此示例以支持别名：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">Categories</span> <span class="pl-c1">=</span> <span class="pl-v">Product</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Tag</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">as</span>: <span class="pl-s">'categories'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-v">Product</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">id</span>: <span class="pl-c1">1</span><span class="pl-kos">,</span>
  <span class="pl-c1">title</span>: <span class="pl-s">'Chair'</span><span class="pl-kos">,</span>
  <span class="pl-c1">categories</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span> <span class="pl-c1">id</span>: <span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">name</span>: <span class="pl-s">'Alpha'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">{</span> <span class="pl-c1">id</span>: <span class="pl-c1">2</span><span class="pl-kos">,</span> <span class="pl-c1">name</span>: <span class="pl-s">'Beta'</span> <span class="pl-kos">}</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span>
    <span class="pl-c1">association</span>: <span class="pl-v">Categories</span><span class="pl-kos">,</span>
    <span class="pl-c1">as</span>: <span class="pl-s">'categories'</span>
  <span class="pl-kos">}</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)<br /><br /></span></pre>
  <h1>Advanced M:N Associations - 高级 M:N 关联</h1>
  <p>阅读本指南之前,请确保已阅读&nbsp;<a href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/core-concepts/assocs.md">关联指南</a>.</p>
  <p>让我们从&nbsp;<code>User</code>&nbsp;和&nbsp;<code>Profile</code>&nbsp;之间的多对多关系示例开始.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">User</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'user'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">username</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">points</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Profile</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'profile'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>定义多对多关系的最简单方法是：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Profile</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-s">'User_Profiles'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Profile</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">User</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-s">'User_Profiles'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>通过将字符串传递给上面的&nbsp;<code>through</code>,我们要求 Sequelize 自动生成名为&nbsp;<code>User_Profiles</code>&nbsp;的模型作为&nbsp;<em>联结表</em>,该模型只有两列：&nbsp;<code>userId</code>&nbsp;和&nbsp;<code>profileId</code>. 在这两个列上将建立一个复合唯一键.</p>
  <p>我们还可以为自己定义一个模型,以用作联结表.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">User_Profile</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'User_Profile'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span><span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Profile</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-v">User_Profile</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Profile</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">User</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-v">User_Profile</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>以上具有完全相同的效果. 注意,我们没有在&nbsp;<code>User_Profile</code>&nbsp;模型上定义任何属性. 我们将其传递给&nbsp;<code>belongsToMany</code>&nbsp;调用的事实告诉 sequelize 自动创建两个属性&nbsp;<code>userId</code>&nbsp;和&nbsp;<code>profileId</code>,就像其他关联一样,也会导致 Sequelize 自动向其中一个涉及的模型添加列.</p>
  <p>然而,自己定义模型有几个优点. 例如,我们可以在联结表中定义更多列：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">User_Profile</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'User_Profile'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">selfGranted</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">BOOLEAN</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Profile</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-v">User_Profile</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Profile</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">User</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-v">User_Profile</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>这样,我们现在可以在联结表中跟踪额外的信息,即&nbsp;<code>selfGranted</code>&nbsp;布尔值. 例如,当调用&nbsp;<code>user.addProfile()</code>&nbsp;时,我们可以使用&nbsp;<code>through</code>&nbsp;参数传递额外列的值.</p>
  <p>示例:</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">amidala</span> <span class="pl-c1">=</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">username</span>: <span class="pl-s">'p4dm3'</span><span class="pl-kos">,</span> <span class="pl-c1">points</span>: <span class="pl-c1">1000</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">queen</span> <span class="pl-c1">=</span> <span class="pl-v">Profile</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'Queen'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">await</span> <span class="pl-s1">amidala</span><span class="pl-kos">.</span><span class="pl-en">addProfile</span><span class="pl-kos">(</span><span class="pl-s1">queen</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-kos">{</span> <span class="pl-c1">selfGranted</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">result</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span> <span class="pl-c1">username</span>: <span class="pl-s">'p4dm3'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">include</span>: <span class="pl-v">Profile</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">result</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>输出:</p>
  <div class="highlight highlight-source-json">
<pre>{
  <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">4</span>,
  <span class="pl-s"><span class="pl-pds">"</span>username<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>p4dm3<span class="pl-pds">"</span></span>,
  <span class="pl-s"><span class="pl-pds">"</span>points<span class="pl-pds">"</span></span>: <span class="pl-c1">1000</span>,
  <span class="pl-s"><span class="pl-pds">"</span>profiles<span class="pl-pds">"</span></span>: [
    {
      <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">6</span>,
      <span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>queen<span class="pl-pds">"</span></span>,
      <span class="pl-s"><span class="pl-pds">"</span>User_Profile<span class="pl-pds">"</span></span>: {
        <span class="pl-s"><span class="pl-pds">"</span>userId<span class="pl-pds">"</span></span>: <span class="pl-c1">4</span>,
        <span class="pl-s"><span class="pl-pds">"</span>profileId<span class="pl-pds">"</span></span>: <span class="pl-c1">6</span>,
        <span class="pl-s"><span class="pl-pds">"</span>selfGranted<span class="pl-pds">"</span></span>: <span class="pl-c1">false</span>
      }
    }
  ]
}</pre>
  </div>
  <p>你也可以在单个&nbsp;<code>create</code>&nbsp;调用中创建所有关系.</p>
  <p>示例:</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">amidala</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">username</span>: <span class="pl-s">'p4dm3'</span><span class="pl-kos">,</span>
  <span class="pl-c1">points</span>: <span class="pl-c1">1000</span><span class="pl-kos">,</span>
  <span class="pl-c1">profiles</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span>
    <span class="pl-c1">name</span>: <span class="pl-s">'Queen'</span><span class="pl-kos">,</span>
    <span class="pl-c1">User_Profile</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">selfGranted</span>: <span class="pl-c1">true</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-v">Profile</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">const</span> <span class="pl-s1">result</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span> <span class="pl-c1">username</span>: <span class="pl-s">'p4dm3'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">include</span>: <span class="pl-v">Profile</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">result</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>输出:</p>
  <div class="highlight highlight-source-json">
<pre>{
  <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>,
  <span class="pl-s"><span class="pl-pds">"</span>username<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>p4dm3<span class="pl-pds">"</span></span>,
  <span class="pl-s"><span class="pl-pds">"</span>points<span class="pl-pds">"</span></span>: <span class="pl-c1">1000</span>,
  <span class="pl-s"><span class="pl-pds">"</span>profiles<span class="pl-pds">"</span></span>: [
    {
      <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>,
      <span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>Queen<span class="pl-pds">"</span></span>,
      <span class="pl-s"><span class="pl-pds">"</span>User_Profile<span class="pl-pds">"</span></span>: {
        <span class="pl-s"><span class="pl-pds">"</span>selfGranted<span class="pl-pds">"</span></span>: <span class="pl-c1">true</span>,
        <span class="pl-s"><span class="pl-pds">"</span>userId<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>,
        <span class="pl-s"><span class="pl-pds">"</span>profileId<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>
      }
    }
  ]
}</pre>
  </div>
  <p>你可能已经注意到&nbsp;<code>User_Profiles</code>&nbsp;表中没有&nbsp;<code>id</code>&nbsp;字段. 如上所述,它具有复合唯一键. 该复合唯一密钥的名称由 Sequelize 自动选择,但可以使用&nbsp;<code>uniqueKey</code>&nbsp;参数进行自定义：</p>
  <div class="highlight highlight-source-js">
    <pre><span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Profile</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-v">User_Profiles</span><span class="pl-kos">,</span> <span class="pl-c1">uniqueKey</span>: <span class="pl-s">'my_custom_unique'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>如果需要的话,另一种可能是强制联结表像其他标准表一样具有主键. 为此,只需在模型中定义主键:</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">User_Profile</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'User_Profile'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">id</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
    <span class="pl-c1">primaryKey</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
    <span class="pl-c1">autoIncrement</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
    <span class="pl-c1">allowNull</span>: <span class="pl-c1">false</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">selfGranted</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">BOOLEAN</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Profile</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-v">User_Profile</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Profile</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">User</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-v">User_Profile</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>上面的代码当然仍然会创建两列&nbsp;<code>userId</code>&nbsp;和&nbsp;<code>profileId</code>,但是模型不会在其上设置复合唯一键,而是将其&nbsp;<code>id</code>&nbsp;列用作主键. 其他一切仍然可以正常工作.</p>
  <h2><a id="user-content-联结表与普通表以及超级多对多关联" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/advanced-many-to-many.md#%E8%81%94%E7%BB%93%E8%A1%A8%E4%B8%8E%E6%99%AE%E9%80%9A%E8%A1%A8%E4%BB%A5%E5%8F%8A%E8%B6%85%E7%BA%A7%E5%A4%9A%E5%AF%B9%E5%A4%9A%E5%85%B3%E8%81%94" aria-hidden="true"></a>联结表与普通表以及"超级多对多关联"</h2>
  <p>现在,我们将比较上面显示的最后一个"多对多"设置与通常的"一对多"关系的用法,以便最后得出&nbsp;<em>超级多对多关系</em>&nbsp;的概念作为结论.</p>
  <h3><a id="user-content-模型回顾-有少量重命名" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/advanced-many-to-many.md#%E6%A8%A1%E5%9E%8B%E5%9B%9E%E9%A1%BE-%E6%9C%89%E5%B0%91%E9%87%8F%E9%87%8D%E5%91%BD%E5%90%8D" aria-hidden="true"></a>模型回顾 (有少量重命名)</h3>
  <p>为了使事情更容易理解,让我们将&nbsp;<code>User_Profile</code>&nbsp;模型重命名为&nbsp;<code>grant</code>. 请注意,所有操作均与以前相同. 我们的模型是：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">User</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'user'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">username</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">points</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">const</span> <span class="pl-v">Profile</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'profile'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">const</span> <span class="pl-v">Grant</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'grant'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">id</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
    <span class="pl-c1">primaryKey</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
    <span class="pl-c1">autoIncrement</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
    <span class="pl-c1">allowNull</span>: <span class="pl-c1">false</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">selfGranted</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">BOOLEAN</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>我们使用&nbsp;<code>Grant</code>&nbsp;模型作为联结表在&nbsp;<code>User</code>&nbsp;和&nbsp;<code>Profile</code>&nbsp;之间建立了多对多关系：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Profile</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-v">Grant</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Profile</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">User</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-v">Grant</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>这会自动将&nbsp;<code>userId</code>&nbsp;和&nbsp;<code>profileId</code>&nbsp;列添加到&nbsp;<code>Grant</code>&nbsp;模型中.</p>
  <p><strong>注意:</strong>&nbsp;如上所示,我们选择强制&nbsp;<code>grant</code>&nbsp;模型具有单个主键(通常称为&nbsp;<code>id</code>). 对于&nbsp;<em>超级多对多关系</em>(即将定义),这是必需的.</p>
  <h3><a id="user-content-改用一对多关系" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/advanced-many-to-many.md#%E6%94%B9%E7%94%A8%E4%B8%80%E5%AF%B9%E5%A4%9A%E5%85%B3%E7%B3%BB" aria-hidden="true"></a>改用一对多关系</h3>
  <p>除了建立上面定义的多对多关系之外,如果我们执行以下操作怎么办？</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 在 User 和 Grant 之间设置一对多关系</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Grant</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Grant</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">User</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 在Profile 和 Grant 之间也设置一对多关系</span>
<span class="pl-v">Profile</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Grant</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Grant</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Profile</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>结果基本相同！ 这是因为&nbsp;<code>User.hasMany(Grant)</code>&nbsp;和&nbsp;<code>Profile.hasMany(Grant)</code>&nbsp;会分别自动将&nbsp;<code>userId</code>&nbsp;和&nbsp;<code>profileId</code>&nbsp;列添加到&nbsp;<code>Grant</code>&nbsp;中.</p>
  <p>这表明一个多对多关系与两个一对多关系没有太大区别. 数据库中的表看起来相同.</p>
  <p>唯一的区别是你尝试使用 Sequelize 执行预先加载时.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 使用多对多方法,你可以:</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Profile</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Profile</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">User</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// However, you can't do:</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Grant</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Profile</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Grant</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Grant</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">User</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Grant</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Profile</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 另一方面,通过双重一对多方法,你可以:</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Grant</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Profile</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Grant</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Grant</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">User</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Grant</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Profile</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// However, you can't do:</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Profile</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Profile</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">User</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 尽管你可以使用嵌套 include 来模拟那些,如下所示:</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Grant</span><span class="pl-kos">,</span>
    <span class="pl-c1">include</span>: <span class="pl-v">Profile</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 这模拟了 `User.findAll({ include: Profile })`,</span>
    <span class="pl-c">// 但是生成的对象结构有些不同.</span>
    <span class="pl-c">// 原始结构的格式为 `user.profiles[].grant`,</span>
    <span class="pl-c">// 而模拟结构的格式为 `user.grants[].profiles[]`.</span></pre>
  </div>
  <h3><a id="user-content-两全其美超级多对多关系" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/advanced-many-to-many.md#%E4%B8%A4%E5%85%A8%E5%85%B6%E7%BE%8E%E8%B6%85%E7%BA%A7%E5%A4%9A%E5%AF%B9%E5%A4%9A%E5%85%B3%E7%B3%BB" aria-hidden="true"></a>两全其美：超级多对多关系</h3>
  <p>我们可以简单地组合上面显示的两种方法！</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 超级多对多关系</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Profile</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-v">Grant</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Profile</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">User</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-v">Grant</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Grant</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Grant</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">User</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Profile</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Grant</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Grant</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Profile</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>这样,我们可以进行各种预先加载：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 全部可以使用:</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Profile</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Profile</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">User</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Grant</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Profile</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Grant</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Grant</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">User</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Grant</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Profile</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>我们甚至可以执行各种深层嵌套的 include：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span>
      <span class="pl-c1">model</span>: <span class="pl-v">Grant</span><span class="pl-kos">,</span>
      <span class="pl-c1">include</span>: <span class="pl-kos">[</span><span class="pl-v">User</span><span class="pl-kos">,</span> <span class="pl-v">Profile</span><span class="pl-kos">]</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">{</span>
      <span class="pl-c1">model</span>: <span class="pl-v">Profile</span><span class="pl-kos">,</span>
      <span class="pl-c1">include</span>: <span class="pl-kos">{</span>
        <span class="pl-c1">model</span>: <span class="pl-v">User</span><span class="pl-kos">,</span>
        <span class="pl-c1">include</span>: <span class="pl-kos">{</span>
          <span class="pl-c1">model</span>: <span class="pl-v">Grant</span><span class="pl-kos">,</span>
          <span class="pl-c1">include</span>: <span class="pl-kos">[</span><span class="pl-v">User</span><span class="pl-kos">,</span> <span class="pl-v">Profile</span><span class="pl-kos">]</span>
        <span class="pl-kos">}</span>
      <span class="pl-kos">}</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h2><a id="user-content-别名和自定义键名" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/advanced-many-to-many.md#%E5%88%AB%E5%90%8D%E5%92%8C%E8%87%AA%E5%AE%9A%E4%B9%89%E9%94%AE%E5%90%8D" aria-hidden="true"></a>别名和自定义键名</h2>
  <p>与其他关系类似,可以为多对多关系定义别名.</p>
  <p>在继续之前,请回顾<a href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/core-concepts/assocs.md">关联指南</a>上的&nbsp;<code>belongsTo</code>&nbsp;别名示例. 请注意,在这种情况下,定义关联影响 include 完成方式(即传递关联名称)和 Sequelize 为外键选择的名称(在该示例中,<code>leaderId</code>&nbsp;是在&nbsp;<code>Ship</code>&nbsp;模型上创建的) .</p>
  <p>为一个&nbsp;<code>belongsToMany</code>&nbsp;关联定义一个别名也会影响 include 执行的方式：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Product</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Category</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">as</span>: <span class="pl-s">'groups'</span><span class="pl-kos">,</span> <span class="pl-c1">through</span>: <span class="pl-s">'product_categories'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Category</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Product</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">as</span>: <span class="pl-s">'items'</span><span class="pl-kos">,</span> <span class="pl-c1">through</span>: <span class="pl-s">'product_categories'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// [...]</span>

<span class="pl-k">await</span> <span class="pl-v">Product</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Category</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 这无法使用</span>

<span class="pl-k">await</span> <span class="pl-v">Product</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c">// 通过别名这可以使用</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Category</span><span class="pl-kos">,</span>
    <span class="pl-c1">as</span>: <span class="pl-s">'groups'</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">await</span> <span class="pl-v">Product</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-s">'groups'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 这也可以使用</span></pre>
  </div>
  <p>但是,在此处定义别名与外键名称无关. 联结表中创建的两个外键的名称仍由 Sequelize 基于关联的模型的名称构造. 通过检查上面示例中的穿透表生成的 SQL,可以很容易看出这一点：</p>
  <div class="highlight highlight-source-sql">
<pre><span class="pl-k">CREATE</span> <span class="pl-k">TABLE</span> <span class="pl-en">IF</span> NOT EXISTS <span class="pl-s"><span class="pl-pds">`</span>product_categories<span class="pl-pds">`</span></span> (
  <span class="pl-s"><span class="pl-pds">`</span>createdAt<span class="pl-pds">`</span></span> DATETIME <span class="pl-k">NOT NULL</span>,
  <span class="pl-s"><span class="pl-pds">`</span>updatedAt<span class="pl-pds">`</span></span> DATETIME <span class="pl-k">NOT NULL</span>,
  <span class="pl-s"><span class="pl-pds">`</span>productId<span class="pl-pds">`</span></span> <span class="pl-k">INTEGER</span> <span class="pl-k">NOT NULL</span> <span class="pl-k">REFERENCES</span> <span class="pl-s"><span class="pl-pds">`</span>products<span class="pl-pds">`</span></span> (<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span>) <span class="pl-k">ON DELETE CASCADE</span> <span class="pl-k">ON</span> <span class="pl-k">UPDATE</span> CASCADE,
  <span class="pl-s"><span class="pl-pds">`</span>categoryId<span class="pl-pds">`</span></span> <span class="pl-k">INTEGER</span> <span class="pl-k">NOT NULL</span> <span class="pl-k">REFERENCES</span> <span class="pl-s"><span class="pl-pds">`</span>categories<span class="pl-pds">`</span></span> (<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span>) <span class="pl-k">ON DELETE CASCADE</span> <span class="pl-k">ON</span> <span class="pl-k">UPDATE</span> CASCADE,
  <span class="pl-k">PRIMARY KEY</span> (<span class="pl-s"><span class="pl-pds">`</span>productId<span class="pl-pds">`</span></span>, <span class="pl-s"><span class="pl-pds">`</span>categoryId<span class="pl-pds">`</span></span>)
);</pre>
  </div>
  <p>我们可以看到外键是&nbsp;<code>productId</code>&nbsp;和&nbsp;<code>categoryId</code>. 要更改这些名称,Sequelize 分别接受参数&nbsp;<code>foreignKey</code>&nbsp;和&nbsp;<code>otherKey</code>(即,<code>foreignKey</code>&nbsp;定义联结关系中源模型的 key,而&nbsp;<code>otherKey</code>&nbsp;定义目标模型中的 key)：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Product</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Category</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">through</span>: <span class="pl-s">'product_categories'</span><span class="pl-kos">,</span>
  <span class="pl-c1">foreignKey</span>: <span class="pl-s">'objectId'</span><span class="pl-kos">,</span> <span class="pl-c">// 替换 `productId`</span>
  <span class="pl-c1">otherKey</span>: <span class="pl-s">'typeId'</span> <span class="pl-c">// 替换 `categoryId`</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Category</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Product</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">through</span>: <span class="pl-s">'product_categories'</span><span class="pl-kos">,</span>
  <span class="pl-c1">foreignKey</span>: <span class="pl-s">'typeId'</span><span class="pl-kos">,</span> <span class="pl-c">// 替换 `categoryId`</span>
  <span class="pl-c1">otherKey</span>: <span class="pl-s">'objectId'</span> <span class="pl-c">// 替换 `productId`</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>生成 SQL:</p>
  <div class="highlight highlight-source-sql">
<pre><span class="pl-k">CREATE</span> <span class="pl-k">TABLE</span> <span class="pl-en">IF</span> NOT EXISTS <span class="pl-s"><span class="pl-pds">`</span>product_categories<span class="pl-pds">`</span></span> (
  <span class="pl-s"><span class="pl-pds">`</span>createdAt<span class="pl-pds">`</span></span> DATETIME <span class="pl-k">NOT NULL</span>,
  <span class="pl-s"><span class="pl-pds">`</span>updatedAt<span class="pl-pds">`</span></span> DATETIME <span class="pl-k">NOT NULL</span>,
  <span class="pl-s"><span class="pl-pds">`</span>objectId<span class="pl-pds">`</span></span> <span class="pl-k">INTEGER</span> <span class="pl-k">NOT NULL</span> <span class="pl-k">REFERENCES</span> <span class="pl-s"><span class="pl-pds">`</span>products<span class="pl-pds">`</span></span> (<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span>) <span class="pl-k">ON DELETE CASCADE</span> <span class="pl-k">ON</span> <span class="pl-k">UPDATE</span> CASCADE,
  <span class="pl-s"><span class="pl-pds">`</span>typeId<span class="pl-pds">`</span></span> <span class="pl-k">INTEGER</span> <span class="pl-k">NOT NULL</span> <span class="pl-k">REFERENCES</span> <span class="pl-s"><span class="pl-pds">`</span>categories<span class="pl-pds">`</span></span> (<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span>) <span class="pl-k">ON DELETE CASCADE</span> <span class="pl-k">ON</span> <span class="pl-k">UPDATE</span> CASCADE,
  <span class="pl-k">PRIMARY KEY</span> (<span class="pl-s"><span class="pl-pds">`</span>objectId<span class="pl-pds">`</span></span>, <span class="pl-s"><span class="pl-pds">`</span>typeId<span class="pl-pds">`</span></span>)
);</pre>
  </div>
  <p>如上所示,当使用两个&nbsp;<code>belongsToMany</code>&nbsp;调用定义多对多关系时(这是标准方式),应在两个调用中适当地提供&nbsp;<code>foreignKey</code>&nbsp;和&nbsp;<code>otherKey</code>&nbsp;参数. 如果仅在一个调用中传递这些参数,那么 Sequelize 行为将不可靠.</p>
  <h2><a id="user-content-自参照" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/advanced-many-to-many.md#%E8%87%AA%E5%8F%82%E7%85%A7" aria-hidden="true"></a>自参照</h2>
  <p>Sequelize 直观地支持自参照多对多关系：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Person</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Person</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">as</span>: <span class="pl-s">'Children'</span><span class="pl-kos">,</span> <span class="pl-c1">through</span>: <span class="pl-s">'PersonChildren'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span>
<span class="pl-c">// 这将创建表 PersonChildren,该表存储对象的 ID.</span></pre>
  </div>
  <h2><a id="user-content-从联结表中指定属性" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/advanced-many-to-many.md#%E4%BB%8E%E8%81%94%E7%BB%93%E8%A1%A8%E4%B8%AD%E6%8C%87%E5%AE%9A%E5%B1%9E%E6%80%A7" aria-hidden="true"></a>从联结表中指定属性</h2>
  <p>默认情况下,当预先加载多对多关系时,Sequelize 将以以下结构返回数据(基于本指南中的第一个示例)：</p>
  <div class="highlight highlight-source-json">
<pre>// User.findOne({ <span class="pl-ii">include</span>: <span class="pl-ii">Profile</span> })
{
  <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">4</span>,
  <span class="pl-s"><span class="pl-pds">"</span>username<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>p4dm3<span class="pl-pds">"</span></span>,
  <span class="pl-s"><span class="pl-pds">"</span>points<span class="pl-pds">"</span></span>: <span class="pl-c1">1000</span>,
  <span class="pl-s"><span class="pl-pds">"</span>profiles<span class="pl-pds">"</span></span>: [
    {
      <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">6</span>,
      <span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>queen<span class="pl-pds">"</span></span>,
      <span class="pl-s"><span class="pl-pds">"</span>grant<span class="pl-pds">"</span></span>: {
        <span class="pl-s"><span class="pl-pds">"</span>userId<span class="pl-pds">"</span></span>: <span class="pl-c1">4</span>,
        <span class="pl-s"><span class="pl-pds">"</span>profileId<span class="pl-pds">"</span></span>: <span class="pl-c1">6</span>,
        <span class="pl-s"><span class="pl-pds">"</span>selfGranted<span class="pl-pds">"</span></span>: <span class="pl-c1">false</span>
      }
    }
  ]
}</pre>
  </div>
  <p>注意,外部对象是一个&nbsp;<code>User</code>,它具有一个名为&nbsp;<code>profiles</code>&nbsp;的字段,该字段是&nbsp;<code>Profile</code>&nbsp;数组,因此每个&nbsp;<code>Profile</code>&nbsp;都带有一个名为&nbsp;<code>grant</code>&nbsp;的额外字段,这是一个&nbsp;<code>Grant</code>&nbsp;实例.当从多对多关系预先加载时,这是 Sequelize 创建的默认结构.</p>
  <p>但是,如果只需要联结表的某些属性,则可以在&nbsp;<code>attributes</code>&nbsp;参数中为数组提供所需的属性. 例如,如果只需要穿透表中的&nbsp;<code>selfGranted</code>&nbsp;属性：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Profile</span><span class="pl-kos">,</span>
    <span class="pl-c1">through</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">attributes</span>: <span class="pl-kos">[</span><span class="pl-s">'selfGranted'</span><span class="pl-kos">]</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>输出:</p>
  <div class="highlight highlight-source-json">
<pre>{
  <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">4</span>,
  <span class="pl-s"><span class="pl-pds">"</span>username<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>p4dm3<span class="pl-pds">"</span></span>,
  <span class="pl-s"><span class="pl-pds">"</span>points<span class="pl-pds">"</span></span>: <span class="pl-c1">1000</span>,
  <span class="pl-s"><span class="pl-pds">"</span>profiles<span class="pl-pds">"</span></span>: [
    {
      <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">6</span>,
      <span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>queen<span class="pl-pds">"</span></span>,
      <span class="pl-s"><span class="pl-pds">"</span>grant<span class="pl-pds">"</span></span>: {
        <span class="pl-s"><span class="pl-pds">"</span>selfGranted<span class="pl-pds">"</span></span>: <span class="pl-c1">false</span>
      }
    }
  ]
}</pre>
  </div>
  <p>如果你根本不想使用嵌套的&nbsp;<code>grant</code>&nbsp;字段,请使用&nbsp;<code>attributes: []</code>：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Profile</span><span class="pl-kos">,</span>
    <span class="pl-c1">through</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">attributes</span>: <span class="pl-kos">[</span><span class="pl-kos">]</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>输出:</p>
  <div class="highlight highlight-source-json">
<pre>{
  <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">4</span>,
  <span class="pl-s"><span class="pl-pds">"</span>username<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>p4dm3<span class="pl-pds">"</span></span>,
  <span class="pl-s"><span class="pl-pds">"</span>points<span class="pl-pds">"</span></span>: <span class="pl-c1">1000</span>,
  <span class="pl-s"><span class="pl-pds">"</span>profiles<span class="pl-pds">"</span></span>: [
    {
      <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">6</span>,
      <span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>queen<span class="pl-pds">"</span></span>
    }
  ]
}</pre>
  </div>
  <p>如果你使用 mixins(例如&nbsp;<code>user.getProfiles()</code>)而不是查找器方法(例如&nbsp;<code>User.findAll()</code>),则必须使用&nbsp;<code>joinTableAttributes</code>&nbsp;参数：</p>
  <div class="highlight highlight-source-js">
    <pre><span class="pl-s1">someUser</span><span class="pl-kos">.</span><span class="pl-en">getProfiles</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">joinTableAttributes</span>: <span class="pl-kos">[</span><span class="pl-s">'selfGranted'</span><span class="pl-kos">]</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>输出:</p>
  <div class="highlight highlight-source-json">
<pre>[
  {
    <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">6</span>,
    <span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>queen<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>grant<span class="pl-pds">"</span></span>: {
      <span class="pl-s"><span class="pl-pds">"</span>selfGranted<span class="pl-pds">"</span></span>: <span class="pl-c1">false</span>
    }
  }
]</pre>
  </div>
  <h2><a id="user-content-多对多对多关系及更多" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/advanced-many-to-many.md#%E5%A4%9A%E5%AF%B9%E5%A4%9A%E5%AF%B9%E5%A4%9A%E5%85%B3%E7%B3%BB%E5%8F%8A%E6%9B%B4%E5%A4%9A" aria-hidden="true"></a>多对多对多关系及更多</h2>
  <p>思考你正在尝试为游戏锦标赛建模. 有玩家和团队. 团队玩游戏. 然而,玩家可以在锦标赛中(但不能在比赛中间)更换团队. 因此,给定一个特定的游戏,有某些团队参与该游戏,并且每个团队都有一组玩家(针对该游戏).</p>
  <p>因此,我们首先定义三个相关模型：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">Player</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'Player'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">username</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Team</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'Team'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Game</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'Game'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>现在的问题是：如何关联它们？</p>
  <p>首先,我们注意到：</p>
  <ul>
    <li>一个游戏有许多与之相关的团队(正在玩该游戏的团队);</li>
    <li>一个团队可能参加了许多比赛.</li>
  </ul>
  <p>以上观察表明,我们需要在 Game 和 Team 之间建立多对多关系. 让我们使用本指南前面解释的超级多对多关系：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// Game 与 Team 之间的超级多对多关系</span>
<span class="pl-k">const</span> <span class="pl-v">GameTeam</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'GameTeam'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">id</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
    <span class="pl-c1">primaryKey</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
    <span class="pl-c1">autoIncrement</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
    <span class="pl-c1">allowNull</span>: <span class="pl-c1">false</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Team</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Game</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-v">GameTeam</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Game</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Team</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-v">GameTeam</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">GameTeam</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Game</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">GameTeam</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Team</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Game</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">GameTeam</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Team</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">GameTeam</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>关于玩家的部分比较棘手. 我们注意到,组成一个团队的一组球员不仅取决于团队,还取决于正在考虑哪个游戏. 因此,我们不希望玩家与团队之间存在多对多关系. 我们也不希望玩家与游戏之间存在多对多关系. 除了将玩家与任何这些模型相关联之外,我们需要的是玩家与&nbsp;<em>团队－游戏约束</em>&nbsp;之类的关联,因为这是一对(团队加游戏)来定义哪些玩家属于那里 .因此,我们正在寻找的正是联结模型GameTeam本身！并且,我们注意到,由于给定的&nbsp;<em>游戏-团队</em>&nbsp;指定了许多玩家,而同一位玩家可以参与许多&nbsp;<em>游戏-团队</em>,因此我们需要玩家之间的多对多关系和GameTeam！</p>
  <p>为了提供最大的灵活性,让我们在这里再次使用"超级多对多"关系构造：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// Player 与 GameTeam 之间的超级多对多关系</span>
<span class="pl-k">const</span> <span class="pl-v">PlayerGameTeam</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'PlayerGameTeam'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">id</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
    <span class="pl-c1">primaryKey</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
    <span class="pl-c1">autoIncrement</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
    <span class="pl-c1">allowNull</span>: <span class="pl-c1">false</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Player</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">GameTeam</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-v">PlayerGameTeam</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">GameTeam</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Player</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-v">PlayerGameTeam</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">PlayerGameTeam</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Player</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">PlayerGameTeam</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">GameTeam</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Player</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">PlayerGameTeam</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">GameTeam</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">PlayerGameTeam</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>上面的关联正是我们想要的. 这是一个完整的可运行示例：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> Sequelize<span class="pl-kos">,</span> Op<span class="pl-kos">,</span> Model<span class="pl-kos">,</span> DataTypes <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'sequelize'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-s">'sqlite::memory:'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">define</span>: <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span> <span class="pl-c">// 在这个例子中只是为了减少混乱</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Player</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'Player'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">username</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Team</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'Team'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Game</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'Game'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 我们在 Game 和 Team 游戏和团队之间应用超级多对多关系</span>
<span class="pl-k">const</span> <span class="pl-v">GameTeam</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'GameTeam'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">id</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
    <span class="pl-c1">primaryKey</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
    <span class="pl-c1">autoIncrement</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
    <span class="pl-c1">allowNull</span>: <span class="pl-c1">false</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Team</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Game</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-v">GameTeam</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Game</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Team</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-v">GameTeam</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">GameTeam</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Game</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">GameTeam</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Team</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Game</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">GameTeam</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Team</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">GameTeam</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 我们在 Player 和 GameTeam 游戏和团队之间应用超级多对多关系</span>
<span class="pl-k">const</span> <span class="pl-v">PlayerGameTeam</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'PlayerGameTeam'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">id</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
    <span class="pl-c1">primaryKey</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
    <span class="pl-c1">autoIncrement</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
    <span class="pl-c1">allowNull</span>: <span class="pl-c1">false</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Player</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">GameTeam</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-v">PlayerGameTeam</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">GameTeam</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Player</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-v">PlayerGameTeam</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">PlayerGameTeam</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Player</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">PlayerGameTeam</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">GameTeam</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Player</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">PlayerGameTeam</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">GameTeam</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">PlayerGameTeam</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-kos">(</span><span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>

  <span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">sync</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-k">await</span> <span class="pl-v">Player</span><span class="pl-kos">.</span><span class="pl-en">bulkCreate</span><span class="pl-kos">(</span><span class="pl-kos">[</span>
    <span class="pl-kos">{</span> <span class="pl-c1">username</span>: <span class="pl-s">'s0me0ne'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">{</span> <span class="pl-c1">username</span>: <span class="pl-s">'empty'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">{</span> <span class="pl-c1">username</span>: <span class="pl-s">'greenhead'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">{</span> <span class="pl-c1">username</span>: <span class="pl-s">'not_spock'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">{</span> <span class="pl-c1">username</span>: <span class="pl-s">'bowl_of_petunias'</span> <span class="pl-kos">}</span>
  <span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-k">await</span> <span class="pl-v">Game</span><span class="pl-kos">.</span><span class="pl-en">bulkCreate</span><span class="pl-kos">(</span><span class="pl-kos">[</span>
    <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'The Big Clash'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'Winter Showdown'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'Summer Beatdown'</span> <span class="pl-kos">}</span>
  <span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-k">await</span> <span class="pl-v">Team</span><span class="pl-kos">.</span><span class="pl-en">bulkCreate</span><span class="pl-kos">(</span><span class="pl-kos">[</span>
    <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'The Martians'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'The Earthlings'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'The Plutonians'</span> <span class="pl-kos">}</span>
  <span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

  <span class="pl-c">// 让我们开始定义哪些球队参加了哪些比赛.</span>
  <span class="pl-c">// 这可以通过几种方式来完成,例如在每个游戏上调用`.setTeams`.</span>
  <span class="pl-c">// 但是,为简便起见,我们将直接使用 `create` 调用,</span>
  <span class="pl-c">// 直接引用我们想要的 ID. 我们知道 ID 是从 1 开始的.</span>
  <span class="pl-k">await</span> <span class="pl-v">GameTeam</span><span class="pl-kos">.</span><span class="pl-en">bulkCreate</span><span class="pl-kos">(</span><span class="pl-kos">[</span>
    <span class="pl-kos">{</span> <span class="pl-c1">GameId</span>: <span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">TeamId</span>: <span class="pl-c1">1</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>   <span class="pl-c">// 该 GameTeam 将获得 id 1</span>
    <span class="pl-kos">{</span> <span class="pl-c1">GameId</span>: <span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">TeamId</span>: <span class="pl-c1">2</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>   <span class="pl-c">// 该 GameTeam 将获得 id 2</span>
    <span class="pl-kos">{</span> <span class="pl-c1">GameId</span>: <span class="pl-c1">2</span><span class="pl-kos">,</span> <span class="pl-c1">TeamId</span>: <span class="pl-c1">1</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>   <span class="pl-c">// 该 GameTeam 将获得 id 3</span>
    <span class="pl-kos">{</span> <span class="pl-c1">GameId</span>: <span class="pl-c1">2</span><span class="pl-kos">,</span> <span class="pl-c1">TeamId</span>: <span class="pl-c1">3</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>   <span class="pl-c">// 该 GameTeam 将获得 id 4</span>
    <span class="pl-kos">{</span> <span class="pl-c1">GameId</span>: <span class="pl-c1">3</span><span class="pl-kos">,</span> <span class="pl-c1">TeamId</span>: <span class="pl-c1">2</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>   <span class="pl-c">// 该 GameTeam 将获得 id 5</span>
    <span class="pl-kos">{</span> <span class="pl-c1">GameId</span>: <span class="pl-c1">3</span><span class="pl-kos">,</span> <span class="pl-c1">TeamId</span>: <span class="pl-c1">3</span> <span class="pl-kos">}</span>    <span class="pl-c">// 该 GameTeam 将获得 id 6</span>
  <span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

  <span class="pl-c">// 现在让我们指定玩家.</span>
  <span class="pl-c">// 为简便起见,我们仅在第二场比赛(Winter Showdown)中这样做.</span>
  <span class="pl-c">// 比方说,s0me0ne 和 greenhead 效力于 Martians,</span>
  <span class="pl-c">// 而 not_spock 和 bowl_of_petunias 效力于 Plutonians:</span>
  <span class="pl-k">await</span> <span class="pl-v">PlayerGameTeam</span><span class="pl-kos">.</span><span class="pl-en">bulkCreate</span><span class="pl-kos">(</span><span class="pl-kos">[</span>
    <span class="pl-c">// 在 'Winter Showdown' (即 GameTeamIds 3 和 4)中:</span>
    <span class="pl-kos">{</span> <span class="pl-c1">PlayerId</span>: <span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">GameTeamId</span>: <span class="pl-c1">3</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>   <span class="pl-c">// s0me0ne played for The Martians</span>
    <span class="pl-kos">{</span> <span class="pl-c1">PlayerId</span>: <span class="pl-c1">3</span><span class="pl-kos">,</span> <span class="pl-c1">GameTeamId</span>: <span class="pl-c1">3</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>   <span class="pl-c">// greenhead played for The Martians</span>
    <span class="pl-kos">{</span> <span class="pl-c1">PlayerId</span>: <span class="pl-c1">4</span><span class="pl-kos">,</span> <span class="pl-c1">GameTeamId</span>: <span class="pl-c1">4</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>   <span class="pl-c">// not_spock played for The Plutonians</span>
    <span class="pl-kos">{</span> <span class="pl-c1">PlayerId</span>: <span class="pl-c1">5</span><span class="pl-kos">,</span> <span class="pl-c1">GameTeamId</span>: <span class="pl-c1">4</span> <span class="pl-kos">}</span>    <span class="pl-c">// bowl_of_petunias played for The Plutonians</span>
  <span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

  <span class="pl-c">// 现在我们可以进行查询！</span>
  <span class="pl-k">const</span> <span class="pl-s1">game</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Game</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
    <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">name</span>: <span class="pl-s">"Winter Showdown"</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-c1">include</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">model</span>: <span class="pl-v">GameTeam</span><span class="pl-kos">,</span>
      <span class="pl-c1">include</span>: <span class="pl-kos">[</span>
        <span class="pl-kos">{</span>
          <span class="pl-c1">model</span>: <span class="pl-v">Player</span><span class="pl-kos">,</span>
          <span class="pl-c1">through</span>: <span class="pl-kos">{</span> <span class="pl-c1">attributes</span>: <span class="pl-kos">[</span><span class="pl-kos">]</span> <span class="pl-kos">}</span> <span class="pl-c">// 隐藏结果中不需要的 `PlayerGameTeam` 嵌套对象</span>
        <span class="pl-kos">}</span><span class="pl-kos">,</span>
        <span class="pl-v">Team</span>
      <span class="pl-kos">]</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

  <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">`Found game: "<span class="pl-s1"><span class="pl-kos">${</span>game<span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">}</span></span>"`</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-k">for</span> <span class="pl-kos">(</span><span class="pl-k">let</span> <span class="pl-s1">i</span> <span class="pl-c1">=</span> <span class="pl-c1">0</span><span class="pl-kos">;</span> <span class="pl-s1">i</span> <span class="pl-c1">&lt;</span> <span class="pl-s1">game</span><span class="pl-kos">.</span><span class="pl-c1">GameTeams</span><span class="pl-kos">.</span><span class="pl-c1">length</span><span class="pl-kos">;</span> <span class="pl-s1">i</span><span class="pl-c1">++</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">const</span> <span class="pl-s1">team</span> <span class="pl-c1">=</span> <span class="pl-s1">game</span><span class="pl-kos">.</span><span class="pl-c1">GameTeams</span><span class="pl-kos">[</span><span class="pl-s1">i</span><span class="pl-kos">]</span><span class="pl-kos">.</span><span class="pl-c1">Team</span><span class="pl-kos">;</span>
    <span class="pl-k">const</span> <span class="pl-s1">players</span> <span class="pl-c1">=</span> <span class="pl-s1">game</span><span class="pl-kos">.</span><span class="pl-c1">GameTeams</span><span class="pl-kos">[</span><span class="pl-s1">i</span><span class="pl-kos">]</span><span class="pl-kos">.</span><span class="pl-c1">Players</span><span class="pl-kos">;</span>
    <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">`- Team "<span class="pl-s1"><span class="pl-kos">${</span>team<span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">}</span></span>" played game "<span class="pl-s1"><span class="pl-kos">${</span>game<span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">}</span></span>" with the following players:`</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">players</span><span class="pl-kos">.</span><span class="pl-en">map</span><span class="pl-kos">(</span><span class="pl-s1">p</span> <span class="pl-c1">=&gt;</span> <span class="pl-s">`--- <span class="pl-s1"><span class="pl-kos">${</span>p<span class="pl-kos">.</span><span class="pl-c1">username</span><span class="pl-kos">}</span></span>`</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">join</span><span class="pl-kos">(</span><span class="pl-s">'\n'</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>

<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>输出:</p>
  <pre lang="text"><code>Found game: "Winter Showdown"
- Team "The Martians" played game "Winter Showdown" with the following players:
--- s0me0ne
--- greenhead
- Team "The Plutonians" played game "Winter Showdown" with the following players:
--- not_spock
--- bowl_of_petunias
</code></pre>
  <p>因此,这就是我们利用超级多对多关系技术在 Sequelize 中实现三个模型之间的&nbsp;<em>多对多对多</em>&nbsp;关系的方式！</p>
  <p>这个想法可以递归地应用于甚至更复杂的,<em>多对多对......对多</em>&nbsp;关系(尽管有时查询可能会变慢).</p>
  <pre><span class="pl-kos">&nbsp;</span></pre>
  <h1>Association Scopes - 关联作用域</h1>
  <p>本节涉及关联作用域,它们与<a href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/other-topics/scopes.md">模型作用域</a>类似但不相同.</p>
  <p>关联作用域既可以放在关联的模型(关联的目标)上,也可以放在多对多关系的联结表中.</p>
  <h2><a id="user-content-概念" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/association-scopes.md#%E6%A6%82%E5%BF%B5" aria-hidden="true"></a>概念</h2>
  <p>与<a href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/other-topics/scopes.md">模型作用域</a>如何自动应用于模型静态调用(例如&nbsp;<code>Model.scope('foo').findAll()</code>)类似,关联作用域也是一个规则(更确切地说, 一组默认属性和参数),这些属性会自动应用于模型中的实例调用. 这里,<em>实例调用</em>是指从实例(而不是从 Model 本身)调用的方法调用. Mixins 是实例方法的主要示例(<code>instance.getSomething</code>,&nbsp;<code>instance.setSomething</code>,&nbsp;<code>instance.addSomething</code>&nbsp;和&nbsp;<code>instance.createSomething</code>).</p>
  <p>关联作用域的行为就像模型作用域一样,在某种意义上,两者都导致将诸如&nbsp;<code>where</code>&nbsp;子句之类的内容自动应用到查找器调用; 区别在于,关联作用域不是自动应用于静态finder调用(模型范围就是这种情况),而是自动应用于实例finder调用(例如mixins).</p>
  <h2><a id="user-content-示例" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/association-scopes.md#%E7%A4%BA%E4%BE%8B" aria-hidden="true"></a>示例</h2>
  <p>下面显示了模型&nbsp;<code>Foo</code>&nbsp;和&nbsp;<code>Bar</code>&nbsp;之间的一对多关联的关联范围的基本示例.</p>
  <ul>
    <li>
      <p>设置:</p>
      <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">Foo</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'foo'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Bar</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'bar'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">status</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Bar</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
    <span class="pl-c1">scope</span>: <span class="pl-kos">{</span>
        <span class="pl-c1">status</span>: <span class="pl-s">'open'</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-c1">as</span>: <span class="pl-s">'openBars'</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">sync</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">myFoo</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">"My Foo"</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
      </div>
    </li>
    <li>
      <p>设置完成后,调用&nbsp;<code>myFoo.getOpenBars()</code>&nbsp;会生成以下SQL：</p>
      <div class="highlight highlight-source-sql">
<pre><span class="pl-k">SELECT</span>
    <span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span>, <span class="pl-s"><span class="pl-pds">`</span>status<span class="pl-pds">`</span></span>, <span class="pl-s"><span class="pl-pds">`</span>createdAt<span class="pl-pds">`</span></span>, <span class="pl-s"><span class="pl-pds">`</span>updatedAt<span class="pl-pds">`</span></span>, <span class="pl-s"><span class="pl-pds">`</span>fooId<span class="pl-pds">`</span></span>
<span class="pl-k">FROM</span> <span class="pl-s"><span class="pl-pds">`</span>bars<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>bar<span class="pl-pds">`</span></span>
<span class="pl-k">WHERE</span> <span class="pl-s"><span class="pl-pds">`</span>bar<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>status<span class="pl-pds">`</span></span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">'</span>open<span class="pl-pds">'</span></span> <span class="pl-k">AND</span> <span class="pl-s"><span class="pl-pds">`</span>bar<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>fooId<span class="pl-pds">`</span></span> <span class="pl-k">=</span> <span class="pl-c1">1</span>;</pre>
      </div>
    </li>
  </ul>
  <p>这样,我们可以看到,调用&nbsp;<code>.getOpenBars()</code>&nbsp;mixin 之后,关联作用域&nbsp;<code>{ status: 'open' }</code>&nbsp;被自动应用到生成的 SQL 的&nbsp;<code>WHERE</code>&nbsp;子句中.</p>
  <h2><a id="user-content-在标准作用域内实现相同的行为" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/association-scopes.md#%E5%9C%A8%E6%A0%87%E5%87%86%E4%BD%9C%E7%94%A8%E5%9F%9F%E5%86%85%E5%AE%9E%E7%8E%B0%E7%9B%B8%E5%90%8C%E7%9A%84%E8%A1%8C%E4%B8%BA" aria-hidden="true"></a>在标准作用域内实现相同的行为</h2>
  <p>我们可以使用标准作用域实现相同的行为：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// Foo.hasMany(Bar, {</span>
<span class="pl-c">//     scope: {</span>
<span class="pl-c">//         status: 'open'</span>
<span class="pl-c">//     },</span>
<span class="pl-c">//     as: 'openBars'</span>
<span class="pl-c">// });</span>

<span class="pl-v">Bar</span><span class="pl-kos">.</span><span class="pl-en">addScope</span><span class="pl-kos">(</span><span class="pl-s">'open'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
    <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
        <span class="pl-c1">status</span>: <span class="pl-s">'open'</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Bar</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Bar</span><span class="pl-kos">.</span><span class="pl-en">scope</span><span class="pl-kos">(</span><span class="pl-s">'open'</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">as</span>: <span class="pl-s">'openBars'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>使用上面的代码,<code>myFoo.getOpenBars()</code>&nbsp;产生与上面所示相同的 SQL.</p>
  <pre><span class="pl-kos">&nbsp;</span></pre>
  <h1>Polymorphic Associations - 多态关联</h1>
  <p><em><strong>注意:</strong>&nbsp;如本指南所述,在 Sequelize 中使用多态关联时应谨慎行事. 不要只是从此处复制粘贴代码,否则你可能会容易出错并在代码中引入错误. 请确保你了解发生了什么.</em></p>
  <h2><a id="user-content-概念" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/polymorphic-associations.md#%E6%A6%82%E5%BF%B5" aria-hidden="true"></a>概念</h2>
  <p>一个&nbsp;<strong>多态关联</strong>&nbsp;由使用同一外键发生的两个(或多个)关联组成.</p>
  <p>例如,考虑模型&nbsp;<code>Image</code>,&nbsp;<code>Video</code>&nbsp;和&nbsp;<code>Comment</code>. 前两个代表用户可能发布的内容. 我们希望允许将评论放在两者中. 这样,我们立即想到建立以下关联：</p>
  <ul>
    <li>
      <p><code>Image</code>&nbsp;和&nbsp;<code>Comment</code>&nbsp;之间的一对多关联:</p>
      <div class="highlight highlight-source-js">
<pre><span class="pl-v">Image</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Comment</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Comment</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Image</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
      </div>
    </li>
    <li>
      <p><code>Video</code>&nbsp;和&nbsp;<code>Comment</code>&nbsp;之间的一对多关联:</p>
      <div class="highlight highlight-source-js">
<pre><span class="pl-v">Video</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Comment</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Comment</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Video</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
      </div>
    </li>
  </ul>
  <p>但是,以上操作将导致 Sequelize 在&nbsp;<code>Comment</code>&nbsp;表上创建两个外键：&nbsp;<code>ImageId</code>&nbsp;和&nbsp;<code>VideoId</code>. 这是不理想的,因为这种结构使评论看起来可以同时附加到一个图像和一个视频上,这是不正确的. 取而代之的是,我们真正想要的是一个多态关联,其中一个&nbsp;<code>Comment</code>&nbsp;指向一个&nbsp;<strong>可评论</strong>,它是表示&nbsp;<code>Image</code>&nbsp;或&nbsp;<code>Video</code>&nbsp;之一的抽象多态实体.</p>
  <p>在继续配置此类关联之前,让我们看看如何使用它：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">image</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Image</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">url</span>: <span class="pl-s">"https://placekitten.com/408/287"</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">comment</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">image</span><span class="pl-kos">.</span><span class="pl-en">createComment</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">content</span>: <span class="pl-s">"Awesome!"</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">comment</span><span class="pl-kos">.</span><span class="pl-c1">commentableId</span> <span class="pl-c1">===</span> <span class="pl-s1">image</span><span class="pl-kos">.</span><span class="pl-c1">id</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// true</span>

<span class="pl-c">// 我们还可以检索与评论关联的可评论类型.</span>
<span class="pl-c">// 下面显示了相关的可注释实例的模型名称.</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">comment</span><span class="pl-kos">.</span><span class="pl-c1">commentableType</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// "Image"</span>

<span class="pl-c">// 我们可以使用多态方法来检索相关的可评论内容,</span>
<span class="pl-c">// 而不必关心它是图像还是视频.</span>
<span class="pl-k">const</span> <span class="pl-s1">associatedCommentable</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">comment</span><span class="pl-kos">.</span><span class="pl-en">getCommentable</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 在此示例中,`associatedCommentable` 与 `image` 是同一件事：</span>
<span class="pl-k">const</span> <span class="pl-s1">isDeepEqual</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'deep-equal'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">isDeepEqual</span><span class="pl-kos">(</span><span class="pl-s1">image</span><span class="pl-kos">,</span> <span class="pl-s1">commentable</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// true</span></pre>
  </div>
  <h2><a id="user-content-配置一对多多态关联" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/polymorphic-associations.md#%E9%85%8D%E7%BD%AE%E4%B8%80%E5%AF%B9%E5%A4%9A%E5%A4%9A%E6%80%81%E5%85%B3%E8%81%94" aria-hidden="true"></a>配置一对多多态关联</h2>
  <p>要为上述示例(这是一对多多态关联的示例)设置多态关联,我们需要执行以下步骤：</p>
  <ul>
    <li>在&nbsp;<code>Comment</code>&nbsp;模型中定义一个名为&nbsp;<code>commentableType</code>&nbsp;的字符串字段;</li>
    <li>在&nbsp;<code>Image</code>/<code>Video</code>&nbsp;和&nbsp;<code>Comment</code>&nbsp;之间定义&nbsp;<code>hasMany</code>&nbsp;和&nbsp;<code>belongsTo</code>&nbsp;关联:
      <ul>
        <li>禁用约束(即使用&nbsp;<code>{ constraints: false }</code>),因为同一个外键引用了多个表;</li>
        <li>指定适当的&nbsp;<a href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/advanced-association-concepts/association-scopes.md">关联作用域</a>;</li>
      </ul>
    </li>
    <li>为了适当地支持延迟加载,请在&nbsp;<code>Comment</code>&nbsp;模型上定义一个名为&nbsp;<code>getCommentable</code>&nbsp;的新实例方法,该方法在后台调用正确的 mixin 来获取适当的注释对象;</li>
    <li>为了正确支持预先加载,请在&nbsp;<code>Comment</code>&nbsp;模型上定义一个&nbsp;<code>afterFind</code>&nbsp;hook,该 hook 将在每个实例中自动填充&nbsp;<code>commentable</code>&nbsp;字段;</li>
    <li>为了防止预先加载的 bug/错误,你还可以在相同的&nbsp;<code>afterFind</code>&nbsp;hook 中从 Comment 实例中删除具体字段&nbsp;<code>image</code>&nbsp;和&nbsp;<code>video</code>,仅保留抽象的&nbsp;<code>commentable</code>&nbsp;字段可用.</li>
  </ul>
  <p>这是一个示例:</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// Helper 方法</span>
<span class="pl-k">const</span> <span class="pl-en">uppercaseFirst</span> <span class="pl-c1">=</span> <span class="pl-s1">str</span> <span class="pl-c1">=&gt;</span> <span class="pl-s">`<span class="pl-s1"><span class="pl-kos">${</span>str<span class="pl-kos">[</span><span class="pl-c1">0</span><span class="pl-kos">]</span><span class="pl-kos">.</span><span class="pl-en">toUpperCase</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">}</span></span><span class="pl-s1"><span class="pl-kos">${</span>str<span class="pl-kos">.</span><span class="pl-en">substr</span><span class="pl-kos">(</span><span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">}</span></span>`</span><span class="pl-kos">;</span>

<span class="pl-k">class</span> <span class="pl-v">Image</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">Image</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">title</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">url</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> sequelize<span class="pl-kos">,</span> <span class="pl-c1">modelName</span>: <span class="pl-s">'image'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">class</span> <span class="pl-v">Video</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">Video</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">title</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">text</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> sequelize<span class="pl-kos">,</span> <span class="pl-c1">modelName</span>: <span class="pl-s">'video'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">class</span> <span class="pl-v">Comment</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span>
  <span class="pl-en">getCommentable</span><span class="pl-kos">(</span><span class="pl-s1">options</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">if</span> <span class="pl-kos">(</span>!<span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">commentableType</span><span class="pl-kos">)</span> <span class="pl-k">return</span> <span class="pl-v">Promise</span><span class="pl-kos">.</span><span class="pl-en">resolve</span><span class="pl-kos">(</span><span class="pl-c1">null</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">const</span> <span class="pl-s1">mixinMethodName</span> <span class="pl-c1">=</span> <span class="pl-s">`get<span class="pl-s1"><span class="pl-kos">${</span><span class="pl-en">uppercaseFirst</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">commentableType</span><span class="pl-kos">)</span><span class="pl-kos">}</span></span>`</span><span class="pl-kos">;</span>
    <span class="pl-k">return</span> <span class="pl-smi">this</span><span class="pl-kos">[</span><span class="pl-s1">mixinMethodName</span><span class="pl-kos">]</span><span class="pl-kos">(</span><span class="pl-s1">options</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span>
<span class="pl-v">Comment</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">title</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">commentableId</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
  <span class="pl-c1">commentableType</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> sequelize<span class="pl-kos">,</span> <span class="pl-c1">modelName</span>: <span class="pl-s">'comment'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-v">Image</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Comment</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">foreignKey</span>: <span class="pl-s">'commentableId'</span><span class="pl-kos">,</span>
  <span class="pl-c1">constraints</span>: <span class="pl-c1">false</span><span class="pl-kos">,</span>
  <span class="pl-c1">scope</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">commentableType</span>: <span class="pl-s">'image'</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Comment</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Image</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">foreignKey</span>: <span class="pl-s">'commentableId'</span><span class="pl-kos">,</span> <span class="pl-c1">constraints</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-v">Video</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Comment</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">foreignKey</span>: <span class="pl-s">'commentableId'</span><span class="pl-kos">,</span>
  <span class="pl-c1">constraints</span>: <span class="pl-c1">false</span><span class="pl-kos">,</span>
  <span class="pl-c1">scope</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">commentableType</span>: <span class="pl-s">'video'</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Comment</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Video</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">foreignKey</span>: <span class="pl-s">'commentableId'</span><span class="pl-kos">,</span> <span class="pl-c1">constraints</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-v">Comment</span><span class="pl-kos">.</span><span class="pl-en">addHook</span><span class="pl-kos">(</span><span class="pl-s">"afterFind"</span><span class="pl-kos">,</span> <span class="pl-s1">findResult</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-k">if</span> <span class="pl-kos">(</span>!<span class="pl-v">Array</span><span class="pl-kos">.</span><span class="pl-en">isArray</span><span class="pl-kos">(</span><span class="pl-s1">findResult</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-s1">findResult</span> <span class="pl-c1">=</span> <span class="pl-kos">[</span><span class="pl-s1">findResult</span><span class="pl-kos">]</span><span class="pl-kos">;</span>
  <span class="pl-k">for</span> <span class="pl-kos">(</span><span class="pl-k">const</span> <span class="pl-s1">instance</span> <span class="pl-k">of</span> <span class="pl-s1">findResult</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">instance</span><span class="pl-kos">.</span><span class="pl-c1">commentableType</span> <span class="pl-c1">===</span> <span class="pl-s">"image"</span> <span class="pl-c1">&amp;&amp;</span> <span class="pl-s1">instance</span><span class="pl-kos">.</span><span class="pl-c1">image</span> !== <span class="pl-c1">undefined</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-s1">instance</span><span class="pl-kos">.</span><span class="pl-c1">commentable</span> <span class="pl-c1">=</span> <span class="pl-s1">instance</span><span class="pl-kos">.</span><span class="pl-c1">image</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">instance</span><span class="pl-kos">.</span><span class="pl-c1">commentableType</span> <span class="pl-c1">===</span> <span class="pl-s">"video"</span> <span class="pl-c1">&amp;&amp;</span> <span class="pl-s1">instance</span><span class="pl-kos">.</span><span class="pl-c1">video</span> !== <span class="pl-c1">undefined</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-s1">instance</span><span class="pl-kos">.</span><span class="pl-c1">commentable</span> <span class="pl-c1">=</span> <span class="pl-s1">instance</span><span class="pl-kos">.</span><span class="pl-c1">video</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
    <span class="pl-c">// 防止错误:</span>
    <span class="pl-k">delete</span> <span class="pl-s1">instance</span><span class="pl-kos">.</span><span class="pl-c1">image</span><span class="pl-kos">;</span>
    <span class="pl-k">delete</span> <span class="pl-s1">instance</span><span class="pl-kos">.</span><span class="pl-c1">dataValues</span><span class="pl-kos">.</span><span class="pl-c1">image</span><span class="pl-kos">;</span>
    <span class="pl-k">delete</span> <span class="pl-s1">instance</span><span class="pl-kos">.</span><span class="pl-c1">video</span><span class="pl-kos">;</span>
    <span class="pl-k">delete</span> <span class="pl-s1">instance</span><span class="pl-kos">.</span><span class="pl-c1">dataValues</span><span class="pl-kos">.</span><span class="pl-c1">video</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>由于&nbsp;<code>commentableId</code>&nbsp;列引用了多个表(本例中为两个表),因此我们无法向其添加&nbsp;<code>REFERENCES</code>&nbsp;约束. 这就是为什么使用&nbsp;<code>constraints: false</code>&nbsp;参数的原因.</p>
  <p>注意,在上面的代码中:</p>
  <ul>
    <li><em>Image -&gt; Comment</em>&nbsp;关联定义了一个关联作用域:&nbsp;<code>{ commentableType: 'image' }</code></li>
    <li><em>Video -&gt; Comment</em>&nbsp;关联定义了一个关联作用域:&nbsp;<code>{ commentableType: 'video' }</code></li>
  </ul>
  <p>使用关联函数时,这些作用域会自动应用(如<a href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/advanced-association-concepts/association-scopes.md">关联作用域</a>指南中所述). 以下是一些示例及其生成的 SQL 语句：</p>
  <ul>
    <li>
      <p><code>image.getComments()</code>:</p>
      <div class="highlight highlight-source-sql">
<pre><span class="pl-k">SELECT</span> <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>title<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>commentableType<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>commentableId<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>createdAt<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>updatedAt<span class="pl-pds">"</span></span>
<span class="pl-k">FROM</span> <span class="pl-s"><span class="pl-pds">"</span>comments<span class="pl-pds">"</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">"</span>comment<span class="pl-pds">"</span></span>
<span class="pl-k">WHERE</span> <span class="pl-s"><span class="pl-pds">"</span>comment<span class="pl-pds">"</span></span>.<span class="pl-s"><span class="pl-pds">"</span>commentableType<span class="pl-pds">"</span></span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">'</span>image<span class="pl-pds">'</span></span> <span class="pl-k">AND</span> <span class="pl-s"><span class="pl-pds">"</span>comment<span class="pl-pds">"</span></span>.<span class="pl-s"><span class="pl-pds">"</span>commentableId<span class="pl-pds">"</span></span> <span class="pl-k">=</span> <span class="pl-c1">1</span>;</pre>
      </div>
    </li>
  </ul>
  <p>在这里我们可以看到&nbsp;<code>`comment`.`commentableType` = 'image'</code>&nbsp;已自动添加到生成的 SQL 的&nbsp;<code>WHERE</code>&nbsp;子句中. 这正是我们想要的行为.</p>
  <ul>
    <li>
      <p><code>image.createComment({ title: 'Awesome!' })</code>:</p>
      <div class="highlight highlight-source-sql">
<pre><span class="pl-k">INSERT INTO</span> <span class="pl-s"><span class="pl-pds">"</span>comments<span class="pl-pds">"</span></span> (
  <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>title<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>commentableType<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>commentableId<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>createdAt<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>updatedAt<span class="pl-pds">"</span></span>
) <span class="pl-k">VALUES</span> (
  DEFAULT, <span class="pl-s"><span class="pl-pds">'</span>Awesome!<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>image<span class="pl-pds">'</span></span>, <span class="pl-c1">1</span>,
  <span class="pl-s"><span class="pl-pds">'</span>2018-04-17 05:36:40.454 +00:00<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>2018-04-17 05:36:40.454 +00:00<span class="pl-pds">'</span></span>
) RETURNING <span class="pl-k">*</span>;</pre>
      </div>
    </li>
    <li>
      <p><code>image.addComment(comment)</code>:</p>
      <div class="highlight highlight-source-sql">
<pre><span class="pl-k">UPDATE</span> <span class="pl-s"><span class="pl-pds">"</span>comments<span class="pl-pds">"</span></span>
<span class="pl-k">SET</span> <span class="pl-s"><span class="pl-pds">"</span>commentableId<span class="pl-pds">"</span></span><span class="pl-k">=</span><span class="pl-c1">1</span>, <span class="pl-s"><span class="pl-pds">"</span>commentableType<span class="pl-pds">"</span></span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">'</span>image<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">"</span>updatedAt<span class="pl-pds">"</span></span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">'</span>2018-04-17 05:38:43.948 +00:00<span class="pl-pds">'</span></span>
<span class="pl-k">WHERE</span> <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span> <span class="pl-k">IN</span> (<span class="pl-c1">1</span>)</pre>
      </div>
    </li>
  </ul>
  <h3><a id="user-content-多态延迟加载" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/polymorphic-associations.md#%E5%A4%9A%E6%80%81%E5%BB%B6%E8%BF%9F%E5%8A%A0%E8%BD%BD" aria-hidden="true"></a>多态延迟加载</h3>
  <p><code>Comment</code>&nbsp;上的&nbsp;<code>getCommentable</code>&nbsp;实例方法为延迟加载相关的 commentable 提供了一种抽象 - 无论注释属于 Image 还是 Video,都可以工作.</p>
  <p>通过简单地将&nbsp;<code>commentableType</code>&nbsp;字符串转换为对正确的 mixin(&nbsp;<code>getImage</code>&nbsp;或&nbsp;<code>getVideo</code>)的调用即可工作.</p>
  <p>注意上面的&nbsp;<code>getCommentable</code>&nbsp;实现：</p>
  <ul>
    <li>不存在关联时返回&nbsp;<code>null</code>;</li>
    <li>允许你将参数对象传递给&nbsp;<code>getCommentable(options)</code>,就像其他任何标准 Sequelize 方法一样. 对于示例,这对于指定 where 条件或 include 条件很有用.</li>
  </ul>
  <h3><a id="user-content-多态预先加载" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/polymorphic-associations.md#%E5%A4%9A%E6%80%81%E9%A2%84%E5%85%88%E5%8A%A0%E8%BD%BD" aria-hidden="true"></a>多态预先加载</h3>
  <p>现在,我们希望对一个(或多个)注释执行关联的可评论对象的多态预先加载. 我们想要实现类似以下的东西：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">comment</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Comment</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span> <span class="pl-c">/* ... */</span> <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">comment</span><span class="pl-kos">.</span><span class="pl-c1">commentable</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 这是我们的目标</span></pre>
  </div>
  <p>解决的办法是告诉 Sequelize 同时包含图像和视频,以便上面定义的&nbsp;<code>afterFind</code>&nbsp;hook可以完成工作,并自动向实例对象添加&nbsp;<code>commentable</code>&nbsp;字段,以提供所需的抽象.</p>
  <p>示例:</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">comments</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Comment</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span><span class="pl-v">Image</span><span class="pl-kos">,</span> <span class="pl-v">Video</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">for</span> <span class="pl-kos">(</span><span class="pl-k">const</span> <span class="pl-s1">comment</span> <span class="pl-k">of</span> <span class="pl-s1">comments</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-k">const</span> <span class="pl-s1">message</span> <span class="pl-c1">=</span> <span class="pl-s">`Found comment #<span class="pl-s1"><span class="pl-kos">${</span>comment<span class="pl-kos">.</span><span class="pl-c1">id</span><span class="pl-kos">}</span></span> with <span class="pl-s1"><span class="pl-kos">${</span>comment<span class="pl-kos">.</span><span class="pl-c1">commentableType</span><span class="pl-kos">}</span></span> commentable:`</span><span class="pl-kos">;</span>
  <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">message</span><span class="pl-kos">,</span> <span class="pl-s1">comment</span><span class="pl-kos">.</span><span class="pl-c1">commentable</span><span class="pl-kos">.</span><span class="pl-en">toJSON</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre>
  </div>
  <p>输出:</p>
  <pre lang="text"><code>Found comment #1 with image commentable: { id: 1,
  title: 'Meow',
  url: 'https://placekitten.com/408/287',
  createdAt: 2019-12-26T15:04:53.047Z,
  updatedAt: 2019-12-26T15:04:53.047Z }
</code></pre>
  <h3><a id="user-content-注意---可能无效的-预先延迟-加载" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/polymorphic-associations.md#%E6%B3%A8%E6%84%8F---%E5%8F%AF%E8%83%BD%E6%97%A0%E6%95%88%E7%9A%84-%E9%A2%84%E5%85%88%E5%BB%B6%E8%BF%9F-%E5%8A%A0%E8%BD%BD" aria-hidden="true"></a>注意 - 可能无效的 预先/延迟 加载!</h3>
  <p>注释&nbsp;<code>Foo</code>,其&nbsp;<code>commentableId</code>&nbsp;为 2,而&nbsp;<code>commentableType</code>&nbsp;为&nbsp;<code>image</code>. 然后&nbsp;<code>Image A</code>&nbsp;和&nbsp;<code>Video X</code>&nbsp;的 ID 都恰好等于 2.从概念上讲,很明显,<code>Video X</code>&nbsp;与&nbsp;<code>Foo</code>&nbsp;没有关联,因为即使其 ID 为 2,<code>Foo</code>&nbsp;的&nbsp;<code>commentableType</code>&nbsp;是&nbsp;<code>image</code>,而不是&nbsp;<code>video</code>. 然而,这种区分仅在 Sequelize 的&nbsp;<code>getCommentable</code>&nbsp;和我们在上面创建的 hook 执行的抽象级别上进行.</p>
  <p>这意味着如果在上述情况下调用&nbsp;<code>Comment.findAll({ include: Video })</code>,<code>Video X</code>&nbsp;将被预先加载到&nbsp;<code>Foo</code>&nbsp;中. 幸运的是,我们的&nbsp;<code>afterFind</code>&nbsp;hook将自动删除它,以帮助防止错误. 你了解发生了什么是非常重要的.</p>
  <p>防止此类错误的最好方法是&nbsp;<strong>不惜一切代价直接使用具体的访问器和mixin</strong>&nbsp;(例如&nbsp;<code>.image</code>,&nbsp;<code>.getVideo()</code>,&nbsp;<code>.setImage()</code>&nbsp;等) ,总是喜欢我们创建的抽象,例如&nbsp;<code>.getCommentable()</code>&nbsp;and&nbsp;<code>.commentable</code>. 如果由于某种原因确实需要访问预先加载的&nbsp;<code>.image</code>&nbsp;和&nbsp;<code>.video</code>&nbsp;请确保将其包装在类型检查中,例如&nbsp;<code>comment.commentableType === 'image'</code>.</p>
  <h2><a id="user-content-配置多对多多态关联" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/polymorphic-associations.md#%E9%85%8D%E7%BD%AE%E5%A4%9A%E5%AF%B9%E5%A4%9A%E5%A4%9A%E6%80%81%E5%85%B3%E8%81%94" aria-hidden="true"></a>配置多对多多态关联</h2>
  <p>在上面的示例中,我们将模型&nbsp;<code>Image</code>&nbsp;和&nbsp;<code>Video</code>&nbsp;抽象称为&nbsp;<em>commentables</em>,其中一个&nbsp;<em>commentable</em>&nbsp;具有很多注释. 但是,一个给定的注释将属于一个&nbsp;<em>commentable</em>&nbsp;- 这就是为什么整个情况都是一对多多态关联的原因.</p>
  <p>现在,考虑多对多多态关联,而不是考虑注释,我们将考虑标签. 为了方便起见,我们现在将它们称为&nbsp;<em>taggables</em>,而不是将它们称为&nbsp;<em>commentables</em>. 一个&nbsp;<em>taggable</em>&nbsp;可以具有多个标签,同时一个标签可以放置在多个&nbsp;<em>taggables</em>&nbsp;中.</p>
  <p>为此设置如下：</p>
  <ul>
    <li>明确定义联结模型,将两个外键指定为&nbsp;<code>tagId</code>&nbsp;和&nbsp;<code>taggableId</code>(这样,它是&nbsp;<code>Tag</code>&nbsp;与&nbsp;<em>taggable</em>&nbsp;抽象概念之间多对多关系的联结模型);</li>
    <li>在联结模型中定义一个名为&nbsp;<code>taggableType</code>&nbsp;的字符串字段;</li>
    <li>定义两个模型之间的&nbsp;<code>belongsToMany</code>&nbsp;关联和&nbsp;<code>标签</code>:
      <ul>
        <li>禁用约束 (即, 使用&nbsp;<code>{ constraints: false }</code>), 因为同一个外键引用了多个表;</li>
        <li>指定适当的&nbsp;<a href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/advanced-association-concepts/association-scopes.md">关联作用域</a>;</li>
      </ul>
    </li>
    <li>在&nbsp;<code>Tag</code>&nbsp;模型上定义一个名为&nbsp;<code>getTaggables</code>&nbsp;的新实例方法,该方法在后台调用正确的 mixin 来获取适当的 taggables.</li>
  </ul>
  <p>实践:</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">class</span> <span class="pl-v">Tag</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span>
  <span class="pl-en">getTaggables</span><span class="pl-kos">(</span><span class="pl-s1">options</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">const</span> <span class="pl-s1">images</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">getImages</span><span class="pl-kos">(</span><span class="pl-s1">options</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">const</span> <span class="pl-s1">videos</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">getVideos</span><span class="pl-kos">(</span><span class="pl-s1">options</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-c">// 在单个 taggables 数组中合并 images 和 videos</span>
    <span class="pl-k">return</span> <span class="pl-s1">images</span><span class="pl-kos">.</span><span class="pl-en">concat</span><span class="pl-kos">(</span><span class="pl-s1">videos</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span>
<span class="pl-v">Tag</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> sequelize<span class="pl-kos">,</span> <span class="pl-c1">modelName</span>: <span class="pl-s">'tag'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 在这里,我们明确定义联结模型</span>
<span class="pl-k">class</span> <span class="pl-v">Tag_Taggable</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">Tag_Taggable</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">tagId</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
    <span class="pl-c1">unique</span>: <span class="pl-s">'tt_unique_constraint'</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">taggableId</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
    <span class="pl-c1">unique</span>: <span class="pl-s">'tt_unique_constraint'</span><span class="pl-kos">,</span>
    <span class="pl-c1">references</span>: <span class="pl-c1">null</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">taggableType</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
    <span class="pl-c1">unique</span>: <span class="pl-s">'tt_unique_constraint'</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> sequelize<span class="pl-kos">,</span> <span class="pl-c1">modelName</span>: <span class="pl-s">'tag_taggable'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-v">Image</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Tag</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">through</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Tag_Taggable</span><span class="pl-kos">,</span>
    <span class="pl-c1">unique</span>: <span class="pl-c1">false</span><span class="pl-kos">,</span>
    <span class="pl-c1">scope</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">taggableType</span>: <span class="pl-s">'image'</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">foreignKey</span>: <span class="pl-s">'taggableId'</span><span class="pl-kos">,</span>
  <span class="pl-c1">constraints</span>: <span class="pl-c1">false</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Tag</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Image</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">through</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Tag_Taggable</span><span class="pl-kos">,</span>
    <span class="pl-c1">unique</span>: <span class="pl-c1">false</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">foreignKey</span>: <span class="pl-s">'tagId'</span><span class="pl-kos">,</span>
  <span class="pl-c1">constraints</span>: <span class="pl-c1">false</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-v">Video</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Tag</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">through</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Tag_Taggable</span><span class="pl-kos">,</span>
    <span class="pl-c1">unique</span>: <span class="pl-c1">false</span><span class="pl-kos">,</span>
    <span class="pl-c1">scope</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">taggableType</span>: <span class="pl-s">'video'</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">foreignKey</span>: <span class="pl-s">'taggableId'</span><span class="pl-kos">,</span>
  <span class="pl-c1">constraints</span>: <span class="pl-c1">false</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Tag</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Video</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">through</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Tag_Taggable</span><span class="pl-kos">,</span>
    <span class="pl-c1">unique</span>: <span class="pl-c1">false</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">foreignKey</span>: <span class="pl-s">'tagId'</span><span class="pl-kos">,</span>
  <span class="pl-c1">constraints</span>: <span class="pl-c1">false</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p><code>constraints: false</code>&nbsp;参数禁用引用约束,因为&nbsp;<code>taggableId</code>&nbsp;列引用了多个表,因此我们无法向其添加&nbsp;<code>REFERENCES</code>&nbsp;约束.</p>
  <p>注意下面:</p>
  <ul>
    <li>对&nbsp;<em>Image -&gt; Tag</em>&nbsp;关联定义了一个关联范围:&nbsp;<code>{ taggableType: 'image' }</code></li>
    <li>对&nbsp;<em>Video -&gt; Tag</em>&nbsp;关联定义了一个关联范围:&nbsp;<code>{ taggableType: 'video' }</code></li>
  </ul>
  <p>使用关联函数时,将自动应用这些作用域. 以下是一些示例及其生成的 SQL 语句：</p>
  <ul>
    <li>
      <p><code>image.getTags()</code>:</p>
      <div class="highlight highlight-source-sql">
<pre><span class="pl-k">SELECT</span>
  <span class="pl-s"><span class="pl-pds">`</span>tag<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>name<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>createdAt<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>updatedAt<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>tagId<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable.tagId<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>taggableId<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable.taggableId<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>taggableType<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable.taggableType<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>createdAt<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable.createdAt<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>updatedAt<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable.updatedAt<span class="pl-pds">`</span></span>
<span class="pl-k">FROM</span> <span class="pl-s"><span class="pl-pds">`</span>tags<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag<span class="pl-pds">`</span></span>
<span class="pl-k">INNER JOIN</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggables<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span> <span class="pl-k">ON</span>
  <span class="pl-s"><span class="pl-pds">`</span>tag<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>tagId<span class="pl-pds">`</span></span> <span class="pl-k">AND</span>
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>taggableId<span class="pl-pds">`</span></span> <span class="pl-k">=</span> <span class="pl-c1">1</span> <span class="pl-k">AND</span>
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>taggableType<span class="pl-pds">`</span></span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">'</span>image<span class="pl-pds">'</span></span>;</pre>
      </div>
    </li>
  </ul>
  <p>在这里我们可以看到&nbsp;<code>`tag_taggable`.`taggableType` = 'image'</code>&nbsp;已被自动添加到生成的 SQL 的 WHERE 子句中. 这正是我们想要的行为.</p>
  <ul>
    <li>
      <p><code>tag.getTaggables()</code>:</p>
      <div class="highlight highlight-source-sql">
<pre><span class="pl-k">SELECT</span>
  <span class="pl-s"><span class="pl-pds">`</span>image<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>image<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>url<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>image<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>createdAt<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>image<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>updatedAt<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>tagId<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable.tagId<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>taggableId<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable.taggableId<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>taggableType<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable.taggableType<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>createdAt<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable.createdAt<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>updatedAt<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable.updatedAt<span class="pl-pds">`</span></span>
<span class="pl-k">FROM</span> <span class="pl-s"><span class="pl-pds">`</span>images<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>image<span class="pl-pds">`</span></span>
<span class="pl-k">INNER JOIN</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggables<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span> <span class="pl-k">ON</span>
  <span class="pl-s"><span class="pl-pds">`</span>image<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>taggableId<span class="pl-pds">`</span></span> <span class="pl-k">AND</span>
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>tagId<span class="pl-pds">`</span></span> <span class="pl-k">=</span> <span class="pl-c1">1</span>;

<span class="pl-k">SELECT</span>
  <span class="pl-s"><span class="pl-pds">`</span>video<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>video<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>url<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>video<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>createdAt<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>video<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>updatedAt<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>tagId<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable.tagId<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>taggableId<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable.taggableId<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>taggableType<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable.taggableType<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>createdAt<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable.createdAt<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>updatedAt<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable.updatedAt<span class="pl-pds">`</span></span>
<span class="pl-k">FROM</span> <span class="pl-s"><span class="pl-pds">`</span>videos<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>video<span class="pl-pds">`</span></span>
<span class="pl-k">INNER JOIN</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggables<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span> <span class="pl-k">ON</span>
  <span class="pl-s"><span class="pl-pds">`</span>video<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>taggableId<span class="pl-pds">`</span></span> <span class="pl-k">AND</span>
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>tagId<span class="pl-pds">`</span></span> <span class="pl-k">=</span> <span class="pl-c1">1</span>;</pre>
      </div>
    </li>
  </ul>
  <p>请注意,上述&nbsp;<code>getTaggables()</code>&nbsp;的实现允许你将选项对象传递给&nbsp;<code>getCommentable(options)</code>,就像其他任何标准 Sequelize 方法一样. 例如,这对于指定条件或包含条件很有用.</p>
  <h3><a id="user-content-在目标模型上应用作用域" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/advanced-association-concepts/polymorphic-associations.md#%E5%9C%A8%E7%9B%AE%E6%A0%87%E6%A8%A1%E5%9E%8B%E4%B8%8A%E5%BA%94%E7%94%A8%E4%BD%9C%E7%94%A8%E5%9F%9F" aria-hidden="true"></a>在目标模型上应用作用域</h3>
  <p>在上面的示例中,<code>scope</code>&nbsp;参数(例如&nbsp;<code>scope: { taggableType: 'image' }</code>)应用于&nbsp;<em>联结</em>&nbsp;模型,而不是&nbsp;<em>目标</em>&nbsp;模型,因为它是在&nbsp;<code>through</code>&nbsp;下使用的参数.</p>
  <p>我们还可以在目标模型上应用关联作用域. 我们甚至可以同时进行.</p>
  <p>为了说明这一点,请考虑上述示例在标签和可标记之间的扩展,其中每个标签都有一个状态. 这样,为了获取图像的所有待处理标签,我们可以在&nbsp;<code>Image</code>&nbsp;和&nbsp;<code>Tag</code>&nbsp;之间建立另一个&nbsp;<code>belognsToMany</code>&nbsp;关系,这一次在联结模型上应用作用域,在目标模型上应用另一个作用域：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Image</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Tag</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">through</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Tag_Taggable</span><span class="pl-kos">,</span>
    <span class="pl-c1">unique</span>: <span class="pl-c1">false</span><span class="pl-kos">,</span>
    <span class="pl-c1">scope</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">taggableType</span>: <span class="pl-s">'image'</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">scope</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">status</span>: <span class="pl-s">'pending'</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">as</span>: <span class="pl-s">'pendingTags'</span><span class="pl-kos">,</span>
  <span class="pl-c1">foreignKey</span>: <span class="pl-s">'taggableId'</span><span class="pl-kos">,</span>
  <span class="pl-c1">constraints</span>: <span class="pl-c1">false</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>这样,当调用&nbsp;<code>image.getPendingTags()</code>&nbsp;时,将生成以下 SQL 查询：</p>
  <div class="highlight highlight-source-sql">
<pre><span class="pl-k">SELECT</span>
  <span class="pl-s"><span class="pl-pds">`</span>tag<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>name<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>status<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>createdAt<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>updatedAt<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>tagId<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable.tagId<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>taggableId<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable.taggableId<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>taggableType<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable.taggableType<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>createdAt<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable.createdAt<span class="pl-pds">`</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>updatedAt<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable.updatedAt<span class="pl-pds">`</span></span>
<span class="pl-k">FROM</span> <span class="pl-s"><span class="pl-pds">`</span>tags<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag<span class="pl-pds">`</span></span>
<span class="pl-k">INNER JOIN</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggables<span class="pl-pds">`</span></span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span> <span class="pl-k">ON</span>
  <span class="pl-s"><span class="pl-pds">`</span>tag<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>tagId<span class="pl-pds">`</span></span> <span class="pl-k">AND</span>
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>taggableId<span class="pl-pds">`</span></span> <span class="pl-k">=</span> <span class="pl-c1">1</span> <span class="pl-k">AND</span>
  <span class="pl-s"><span class="pl-pds">`</span>tag_taggable<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>taggableType<span class="pl-pds">`</span></span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">'</span>image<span class="pl-pds">'</span></span>
<span class="pl-k">WHERE</span> (
  <span class="pl-s"><span class="pl-pds">`</span>tag<span class="pl-pds">`</span></span>.<span class="pl-s"><span class="pl-pds">`</span>status<span class="pl-pds">`</span></span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">'</span>pending<span class="pl-pds">'</span></span>
);</pre>
  </div>
  <p>我们可以看到两个作用域都是自动应用的:</p>
  <ul>
    <li><code>`tag_taggable`.`taggableType` = 'image'</code>&nbsp;被自动添加到&nbsp;<code>INNER JOIN</code>;</li>
    <li><code>`tag`.`status` = 'pending'</code> 被自动添加到外部 where 子句.</li>
  </ul>
</div>

<div class="l-title">其它主题</div>
<h1>Dialect-Specific Things - 方言特定事项</h1>
<h2><a id="user-content-基础连接器库" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/dialect-specific-things.md#%E5%9F%BA%E7%A1%80%E8%BF%9E%E6%8E%A5%E5%99%A8%E5%BA%93" aria-hidden="true"></a>基础连接器库</h2>
<h3><a id="user-content-mysql" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/dialect-specific-things.md#mysql" aria-hidden="true"></a>MySQL</h3>
<p>Sequelize 对于 MySQL 使用的基础连接器库是&nbsp;<a href="https://www.npmjs.com/package/mysql2" rel="nofollow">mysql2</a>&nbsp;npm 软件包(1.5.2 或更高版本).</p>
<p>你可以使用 Sequelize 构造函数中的&nbsp;<code>dialectOptions</code>&nbsp;为其提供自定义参数：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-s">'database'</span><span class="pl-kos">,</span> <span class="pl-s">'username'</span><span class="pl-kos">,</span> <span class="pl-s">'password'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">dialect</span>: <span class="pl-s">'mysql'</span><span class="pl-kos">,</span>
  <span class="pl-c1">dialectOptions</span>: <span class="pl-kos">{</span>
    <span class="pl-c">// 你的 mysql2 参数</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span></pre>
</div>
<h3><a id="user-content-mariadb" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/dialect-specific-things.md#mariadb" aria-hidden="true"></a>MariaDB</h3>
<p>Sequelize 对于 MariaDB 使用的基础连接器库是&nbsp;<a href="https://www.npmjs.com/package/mariadb" rel="nofollow">mariadb</a>&nbsp;npm 软件包.</p>
<p>你可以使用 Sequelize 构造函数中的&nbsp;<code>dialectOptions</code>&nbsp;为其提供自定义参数：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-s">'database'</span><span class="pl-kos">,</span> <span class="pl-s">'username'</span><span class="pl-kos">,</span> <span class="pl-s">'password'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">dialect</span>: <span class="pl-s">'mariadb'</span><span class="pl-kos">,</span>
  <span class="pl-c1">dialectOptions</span>: <span class="pl-kos">{</span>
    <span class="pl-c">// 你的 mariadb 参数</span>
    <span class="pl-c">// connectTimeout: 1000</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h3><a id="user-content-sqlite" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/dialect-specific-things.md#sqlite" aria-hidden="true"></a>SQLite</h3>
<p>Sequelize 对于 SQLite 使用的基础连接器库是&nbsp;<a href="https://www.npmjs.com/package/sqlite3" rel="nofollow">sqlite3</a>&nbsp;npm 程序包(版本4.0.0或更高版本).</p>
<p>你可以在 Sequelize 构造函数中使用&nbsp;<code>storage</code>&nbsp;参数指定存储文件(对于内存中的SQLite实例,请使用&nbsp;<code>:memory:</code>).</p>
<p>你可以使用 Sequelize 构造函数中的&nbsp;<code>dialectOptions</code>&nbsp;为其提供自定义参数：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-s">'database'</span><span class="pl-kos">,</span> <span class="pl-s">'username'</span><span class="pl-kos">,</span> <span class="pl-s">'password'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">dialect</span>: <span class="pl-s">'sqlite'</span><span class="pl-kos">,</span>
  <span class="pl-c1">storage</span>: <span class="pl-s">'path/to/database.sqlite'</span> <span class="pl-c">// 或 ':memory:'</span>
  <span class="pl-s1">dialectOptions</span>: <span class="pl-kos">{</span>
    <span class="pl-c">// 你的 sqlite3 参数</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h3><a id="user-content-postgresql" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/dialect-specific-things.md#postgresql" aria-hidden="true"></a>PostgreSQL</h3>
<p>Sequelize 对于 PostgreSQL 使用的基础连接器库是&nbsp;<a href="https://www.npmjs.com/package/pg" rel="nofollow">pg</a>&nbsp;npm 软件包(版本7.0.0或更高版本). 还需要模块&nbsp;<a href="https://www.npmjs.com/package/pg-hstore" rel="nofollow">pg-hstore</a>.</p>
<p>你可以使用 Sequelize 构造函数中的&nbsp;<code>dialectOptions</code>&nbsp;为其提供自定义参数：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-s">'database'</span><span class="pl-kos">,</span> <span class="pl-s">'username'</span><span class="pl-kos">,</span> <span class="pl-s">'password'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">dialect</span>: <span class="pl-s">'postgres'</span><span class="pl-kos">,</span>
  <span class="pl-c1">dialectOptions</span>: <span class="pl-kos">{</span>
    <span class="pl-c">// 你的 pg 参数</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>要通过 Unix 域套接字进行连接,请在&nbsp;<code>host</code>&nbsp;参数中指定套接字目录的路径. 套接字路径必须以&nbsp;<code>/</code>&nbsp;开头.</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-s">'database'</span><span class="pl-kos">,</span> <span class="pl-s">'username'</span><span class="pl-kos">,</span> <span class="pl-s">'password'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">dialect</span>: <span class="pl-s">'postgres'</span><span class="pl-kos">,</span>
  <span class="pl-c1">host</span>: <span class="pl-s">'/path/to/socket_directory'</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h3><a id="user-content-mssql" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/dialect-specific-things.md#mssql" aria-hidden="true"></a>MSSQL</h3>
<p>Sequelize 用于 MSSQL 的基础连接器库是&nbsp;<a href="https://www.npmjs.com/package/tedious" rel="nofollow">tedious</a>&nbsp;npm 软件包(版本6.0.0或更高版本).</p>
<p>你可以使用 Sequelize 构造函数中的&nbsp;<code>dialectOptions.options</code>&nbsp;为其提供自定义参数：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-s">'database'</span><span class="pl-kos">,</span> <span class="pl-s">'username'</span><span class="pl-kos">,</span> <span class="pl-s">'password'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">dialect</span>: <span class="pl-s">'postgres'</span><span class="pl-kos">,</span>
  <span class="pl-c1">dialectOptions</span>: <span class="pl-kos">{</span>
    <span class="pl-c">// 观察 MSSQL 这个嵌套的 `options` 字段</span>
    <span class="pl-c1">options</span>: <span class="pl-kos">{</span>
      <span class="pl-c">// 你的 tedious 参数</span>
      <span class="pl-c1">useUTC</span>: <span class="pl-c1">false</span><span class="pl-kos">,</span>
      <span class="pl-c1">dateFirst</span>: <span class="pl-c1">1</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h4><a id="user-content-mssql-域账户" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/dialect-specific-things.md#mssql-%E5%9F%9F%E8%B4%A6%E6%88%B7" aria-hidden="true"></a>MSSQL 域账户</h4>
<p>为了连接域帐户,请使用以下格式.</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-s">'database'</span><span class="pl-kos">,</span> <span class="pl-c1">null</span><span class="pl-kos">,</span> <span class="pl-c1">null</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">dialect</span>: <span class="pl-s">'mssql'</span><span class="pl-kos">,</span>
  <span class="pl-c1">dialectOptions</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">authentication</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">type</span>: <span class="pl-s">'ntlm'</span><span class="pl-kos">,</span>
      <span class="pl-c1">options</span>: <span class="pl-kos">{</span>
        <span class="pl-c1">domain</span>: <span class="pl-s">'yourDomain'</span><span class="pl-kos">,</span>
        <span class="pl-c1">userName</span>: <span class="pl-s">'username'</span><span class="pl-kos">,</span>
        <span class="pl-c1">password</span>: <span class="pl-s">'password'</span>
      <span class="pl-kos">}</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-c1">options</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">instanceName</span>: <span class="pl-s">'SQLEXPRESS'</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span></pre>
</div>
<h2><a id="user-content-数据类型-timestamp-without-time-zone---仅限--postgresql" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/dialect-specific-things.md#%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B-timestamp-without-time-zone---%E4%BB%85%E9%99%90--postgresql" aria-hidden="true"></a>数据类型: TIMESTAMP WITHOUT TIME ZONE - 仅限 PostgreSQL</h2>
<p>如果你使用的是 PostgreSQL&nbsp;<code>TIMESTAMP WITH TIME ZONE</code>,并且需要将其解析为其他时区,请使用 pg 库自己的解析器：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'pg'</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-c1">types</span><span class="pl-kos">.</span><span class="pl-en">setTypeParser</span><span class="pl-kos">(</span><span class="pl-c1">1114</span><span class="pl-kos">,</span> <span class="pl-s1">stringValue</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-k">return</span> <span class="pl-k">new</span> <span class="pl-v">Date</span><span class="pl-kos">(</span><span class="pl-s1">stringValue</span> <span class="pl-c1">+</span> <span class="pl-s">'+0000'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-c">// 例如 UTC 偏移量. 使用任何你想要的偏移量.</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h2><a id="user-content-数据类型-arrayenum---仅限-postgresql" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/dialect-specific-things.md#%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B-arrayenum---%E4%BB%85%E9%99%90-postgresql" aria-hidden="true"></a>数据类型: ARRAY(ENUM) - 仅限 PostgreSQL</h2>
<p>Array(Enum)类型需要特殊处理. 每当 Sequelize 与数据库对话时,它都必须使用 ENUM 名称转换数组值.</p>
<p>因此,此枚举名称必须遵循这种格式&nbsp;<code>enum_&lt;table_name&gt;_&lt;col_name&gt;</code>. 如果你使用&nbsp;<code>sync</code>,则将自动生成正确的名称.</p>
<h2><a id="user-content-表提示---仅限-mssql" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/dialect-specific-things.md#%E8%A1%A8%E6%8F%90%E7%A4%BA---%E4%BB%85%E9%99%90-mssql" aria-hidden="true"></a>表提示 - 仅限 MSSQL</h2>
<p><code>tableHint</code>&nbsp;属性可用于定义表提示. 提示必须是来自&nbsp;<code>TableHints</code>&nbsp;的值,并且仅在绝对必要时才使用. 当前每个查询仅支持单个表提示.</p>
<p>表提示通过指定某些参数来覆盖 MSSQL 查询优化器的默认行为. 它们仅影响该子句中引用的表或视图.</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> TableHints <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'sequelize'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c">// 添加表提示 NOLOCK</span>
  <span class="pl-c1">tableHint</span>: <span class="pl-v">TableHints</span><span class="pl-kos">.</span><span class="pl-c1">NOLOCK</span>
  <span class="pl-c">// 这将生成 SQL 'WITH (NOLOCK)'</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span></pre>
</div>
<h2><a id="user-content-索引提示---仅限-mysqlmariadb" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/dialect-specific-things.md#%E7%B4%A2%E5%BC%95%E6%8F%90%E7%A4%BA---%E4%BB%85%E9%99%90-mysqlmariadb" aria-hidden="true"></a>索引提示 - 仅限 MySQL/MariaDB</h2>
<p><code>indexHints</code>&nbsp;参数可以用来定义索引提示. 提示类型必须是&nbsp;<code>IndexHints</code>&nbsp;中的值,并且这些值应引用现有索引.</p>
<p>索引提示<a href="https://dev.mysql.com/doc/refman/5.7/en/index-hints.html" rel="nofollow">将覆盖 MySQL 查询优化器的默认行为</a>.</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> IndexHints <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">"sequelize"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">indexHints</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span> <span class="pl-c1">type</span>: <span class="pl-v">IndexHints</span><span class="pl-kos">.</span><span class="pl-c1">USE</span><span class="pl-kos">,</span> <span class="pl-c1">values</span>: <span class="pl-kos">[</span><span class="pl-s">'index_project_on_name'</span><span class="pl-kos">]</span> <span class="pl-kos">}</span>
  <span class="pl-kos">]</span><span class="pl-kos">,</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">id</span>: <span class="pl-kos">{</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">gt</span><span class="pl-kos">]</span>: <span class="pl-c1">623</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-c1">name</span>: <span class="pl-kos">{</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">like</span><span class="pl-kos">]</span>: <span class="pl-s">'Foo %'</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>上面的代码将生成一个如下所示的 MySQL 查询：</p>
<div class="highlight highlight-source-sql">
  <pre><span class="pl-k">SELECT</span> <span class="pl-k">*</span> <span class="pl-k">FROM</span> Project USE INDEX (index_project_on_name) <span class="pl-k">WHERE</span> name <span class="pl-k">LIKE</span> <span class="pl-s"><span class="pl-pds">'</span>FOO %<span class="pl-pds">'</span></span> <span class="pl-k">AND</span> id <span class="pl-k">&gt;</span> <span class="pl-c1">623</span>;</pre>
</div>
<p><code>Sequelize.IndexHints</code>&nbsp;包含&nbsp;<code>USE</code>,&nbsp;<code>FORCE</code>, 和&nbsp;<code>IGNORE</code>.</p>
<p>参考&nbsp;<a href="https://github.com/sequelize/sequelize/issues/9421">Issue #9421</a>&nbsp;有关原始 API 提案.</p>
<h2><a id="user-content-引擎---仅限-mysqlmariadb" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/dialect-specific-things.md#%E5%BC%95%E6%93%8E---%E4%BB%85%E9%99%90-mysqlmariadb" aria-hidden="true"></a>引擎 - 仅限 MySQL/MariaDB</h2>
<p>模型的默认引擎是 InnoDB.</p>
<p>你可以使用&nbsp;<code>engine</code>&nbsp;参数更改模型的引擎(例如,更改为 MyISAM)：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">Person</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'person'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c">/* 属性 */</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">engine</span>: <span class="pl-s">'MYISAM'</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>像模型定义的每个参数一样,也可以使用 Sequelize 构造函数的&nbsp;<code>define</code>&nbsp;参数来全局更改此设置：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-s1">db</span><span class="pl-kos">,</span> <span class="pl-s1">user</span><span class="pl-kos">,</span> <span class="pl-s1">pw</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">define</span>: <span class="pl-kos">{</span> <span class="pl-c1">engine</span>: <span class="pl-s">'MYISAM'</span> <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span></pre>
</div>
<h2><a id="user-content-表注释---仅限-mysqlmariadbpostgresql" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/dialect-specific-things.md#%E8%A1%A8%E6%B3%A8%E9%87%8A---%E4%BB%85%E9%99%90-mysqlmariadbpostgresql" aria-hidden="true"></a>表注释 - 仅限 MySQL/MariaDB/PostgreSQL</h2>
<p>你可以在定义模型时为表指定注释：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">class</span> <span class="pl-v">Person</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">Person</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c">/* 属性 */</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">comment</span>: <span class="pl-s">"I'm a table comment!"</span><span class="pl-kos">,</span>
  sequelize
<span class="pl-kos">}</span><span class="pl-kos">)</span></pre>
</div>
<p>调用&nbsp;<code>sync()</code>&nbsp;时将设置注释.</p>
<p>&nbsp;</p>
<h1>Transactions - 事务</h1>
<p>默认情况下,Sequelize 不使用<a href="https://en.wikipedia.org/wiki/Database_transaction" rel="nofollow">事务</a>. 但是,对于 Sequelize 的生产环境使用,你绝对应该将 Sequelize 配置为使用事务.</p>
<p>Sequelize 支持两种使用事务的方式：</p>
<ol>
  <li>
    <p><strong>非托管事务:</strong>&nbsp;提交和回滚事务应由用户手动完成(通过调用适当的 Sequelize 方法).</p>
  </li>
  <li>
    <p><strong>托管事务</strong>: 如果引发任何错误,Sequelize 将自动回滚事务,否则将提交事务. 另外,如果启用了CLS(连续本地存储),则事务回调中的所有查询将自动接收事务对象.</p>
  </li>
</ol>
<h2><a id="user-content-非托管事务" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/transactions.md#%E9%9D%9E%E6%89%98%E7%AE%A1%E4%BA%8B%E5%8A%A1" aria-hidden="true"></a>非托管事务</h2>
<p>让我们从一个例子开始:</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-c">// 首先,我们开始一个事务并将其保存到变量中</span>
<span class="pl-k">const</span> <span class="pl-s1">t</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">transaction</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">try</span> <span class="pl-kos">{</span>

  <span class="pl-c">// 然后,我们进行一些调用以将此事务作为参数传递:</span>

  <span class="pl-k">const</span> <span class="pl-s1">user</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
    <span class="pl-c1">firstName</span>: <span class="pl-s">'Bart'</span><span class="pl-kos">,</span>
    <span class="pl-c1">lastName</span>: <span class="pl-s">'Simpson'</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">transaction</span>: <span class="pl-s1">t</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

  <span class="pl-k">await</span> <span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-en">addSibling</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
    <span class="pl-c1">firstName</span>: <span class="pl-s">'Lisa'</span><span class="pl-kos">,</span>
    <span class="pl-c1">lastName</span>: <span class="pl-s">'Simpson'</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">transaction</span>: <span class="pl-s1">t</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

  <span class="pl-c">// 如果执行到此行,且没有引发任何错误.</span>
  <span class="pl-c">// 我们提交事务.</span>
  <span class="pl-k">await</span> <span class="pl-s1">t</span><span class="pl-kos">.</span><span class="pl-en">commit</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-kos">}</span> <span class="pl-k">catch</span> <span class="pl-kos">(</span><span class="pl-s1">error</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>

  <span class="pl-c">// 如果执行到达此行,则抛出错误.</span>
  <span class="pl-c">// 我们回滚事务.</span>
  <span class="pl-k">await</span> <span class="pl-s1">t</span><span class="pl-kos">.</span><span class="pl-en">rollback</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-kos">}</span></pre>
</div>
<p>如上所示,<em>非托管事务</em>&nbsp;方法要求你在必要时手动提交和回滚事务.</p>
<h2><a id="user-content-托管事务" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/transactions.md#%E6%89%98%E7%AE%A1%E4%BA%8B%E5%8A%A1" aria-hidden="true"></a>托管事务</h2>
<p>托管事务会自动处理提交或回滚事务. 通过将回调传递给&nbsp;<code>sequelize.transaction</code>&nbsp;来启动托管事务. 这个回调可以是&nbsp;<code>async</code>(通常是)的.</p>
<p>在这种情况下,将发生以下情况：</p>
<ul>
  <li>Sequelize 将自动开始事务并获得事务对象&nbsp;<code>t</code></li>
  <li>然后,Sequelize 将执行你提供的回调,并在其中传递&nbsp;<code>t</code></li>
  <li>如果你的回调抛出错误,Sequelize 将自动回滚事务</li>
  <li>如果你的回调成功,Sequelize 将自动提交事务</li>
  <li>只有这样,<code>sequelize.transaction</code>&nbsp;调用才会解决：
    <ul>
      <li>解决你的回调的决议</li>
      <li>或者,如果你的回调引发错误,则拒绝并抛出错误</li>
    </ul>
  </li>
</ul>
<p>示例代码:</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">try</span> <span class="pl-kos">{</span>

  <span class="pl-k">const</span> <span class="pl-s1">result</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">transaction</span><span class="pl-kos">(</span><span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-s1">t</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>

    <span class="pl-k">const</span> <span class="pl-s1">user</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
      <span class="pl-c1">firstName</span>: <span class="pl-s">'Abraham'</span><span class="pl-kos">,</span>
      <span class="pl-c1">lastName</span>: <span class="pl-s">'Lincoln'</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">transaction</span>: <span class="pl-s1">t</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-k">await</span> <span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-en">setShooter</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
      <span class="pl-c1">firstName</span>: <span class="pl-s">'John'</span><span class="pl-kos">,</span>
      <span class="pl-c1">lastName</span>: <span class="pl-s">'Boothe'</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">transaction</span>: <span class="pl-s1">t</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-k">return</span> <span class="pl-s1">user</span><span class="pl-kos">;</span>

  <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

  <span class="pl-c">// 如果执行到此行,则表示事务已成功提交,`result`是事务返回的结果</span>
  <span class="pl-c">// `result` 就是从事务回调中返回的结果(在这种情况下为 `user`)</span>

<span class="pl-kos">}</span> <span class="pl-k">catch</span> <span class="pl-kos">(</span><span class="pl-s1">error</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>

  <span class="pl-c">// 如果执行到此,则发生错误.</span>
  <span class="pl-c">// 该事务已由 Sequelize 自动回滚！</span>

<span class="pl-kos">}</span></pre>
</div>
<p>注意,<code>t.commit()</code>&nbsp;和&nbsp;<code>t.rollback()</code>&nbsp;没有被直接调用.</p>
<h3><a id="user-content-抛出错误以回滚" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/transactions.md#%E6%8A%9B%E5%87%BA%E9%94%99%E8%AF%AF%E4%BB%A5%E5%9B%9E%E6%BB%9A" aria-hidden="true"></a>抛出错误以回滚</h3>
<p>使用托管事务时,你&nbsp;<em>不应</em>&nbsp;手动提交或回滚事务. 如果所有查询都成功(就不引发任何错误而言),但是你仍然想回滚事务,那么你应该自己引发一个错误：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">transaction</span><span class="pl-kos">(</span><span class="pl-s1">t</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-k">const</span> <span class="pl-s1">user</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
    <span class="pl-c1">firstName</span>: <span class="pl-s">'Abraham'</span><span class="pl-kos">,</span>
    <span class="pl-c1">lastName</span>: <span class="pl-s">'Lincoln'</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">transaction</span>: <span class="pl-s1">t</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

  <span class="pl-c">// 查询成功,但我们仍要回滚！</span>
  <span class="pl-c">// 我们手动引发错误,以便 Sequelize 自动处理所有内容.</span>
  <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-v">Error</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h3><a id="user-content-自动将事务传递给所有查询" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/transactions.md#%E8%87%AA%E5%8A%A8%E5%B0%86%E4%BA%8B%E5%8A%A1%E4%BC%A0%E9%80%92%E7%BB%99%E6%89%80%E6%9C%89%E6%9F%A5%E8%AF%A2" aria-hidden="true"></a>自动将事务传递给所有查询</h3>
<p>在上面的示例中,仍然通过传递&nbsp;<code>{ transaction: t }</code>&nbsp;作为第二个参数来手动传递事务. 要将事务自动传递给所有查询,你必须安装&nbsp;<a href="https://github.com/Jeff-Lewis/cls-hooked">cls-hooked</a>&nbsp;(CLS) 模块,并在自己的代码中实例化命名空间：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">cls</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'cls-hooked'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">namespace</span> <span class="pl-c1">=</span> <span class="pl-s1">cls</span><span class="pl-kos">.</span><span class="pl-en">createNamespace</span><span class="pl-kos">(</span><span class="pl-s">'my-very-own-namespace'</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>要启用 CLS,你必须通过使用 sequelize 构造函数的静态方法来告诉 sequelize 使用哪个命名空间：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">Sequelize</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'sequelize'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-en">useCLS</span><span class="pl-kos">(</span><span class="pl-s1">namespace</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span>...<span class="pl-kos">.</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>注意,<code>useCLS()</code>&nbsp;方法在&nbsp;<em>构建器</em>&nbsp;上,而不在 sequelize 实例上. 这意味着所有实例将共享相同的命名空间,并且 CLS 是全有或全无 - 你不能仅对某些实例启用它.</p>
<p>CLS 的工作方式类似于用于回调的线程本地存储. 实际上,这意味着不同的回调链可以使用 CLS 命名空间访问局部变量. 启用 CLS 时,sequelize 将在创建新事务时在命名空间上设置&nbsp;<code>transaction</code>&nbsp;属性. 由于在回调链中设置的变量是该链的私有变量,因此可以同时存在多个并发事务：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">transaction</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-s1">t1</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-s1">namespace</span><span class="pl-kos">.</span><span class="pl-en">get</span><span class="pl-kos">(</span><span class="pl-s">'transaction'</span><span class="pl-kos">)</span> <span class="pl-c1">===</span> <span class="pl-s1">t1</span><span class="pl-kos">;</span> <span class="pl-c">// true</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">transaction</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-s1">t2</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-s1">namespace</span><span class="pl-kos">.</span><span class="pl-en">get</span><span class="pl-kos">(</span><span class="pl-s">'transaction'</span><span class="pl-kos">)</span> <span class="pl-c1">===</span> <span class="pl-s1">t2</span><span class="pl-kos">;</span> <span class="pl-c">// true</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>在大多数情况下,你不需要直接访问&nbsp;<code>namespace.get('transaction')</code>,因为所有查询都会自动在命名空间上查找事务：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">transaction</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-s1">t1</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-c">// 启用 CLS 后,将在事务内部创建用户</span>
  <span class="pl-k">return</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'Alice'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h2><a id="user-content-并发部分事务" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/transactions.md#%E5%B9%B6%E5%8F%91%E9%83%A8%E5%88%86%E4%BA%8B%E5%8A%A1" aria-hidden="true"></a>并发/部分事务</h2>
<p>你可以在一系列查询中进行并发事务,也可以将某些事务排除在任何事务之外. 使用&nbsp;<code>transaction</code>&nbsp;参数来控制查询属于哪个事务：</p>
<p><strong>注意:</strong>&nbsp;<em>SQLite 不支持同时多个事务.</em></p>
<h3><a id="user-content-启用-cls" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/transactions.md#%E5%90%AF%E7%94%A8-cls" aria-hidden="true"></a>启用 CLS</h3>
<div class="highlight highlight-source-js">
<pre><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">transaction</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-s1">t1</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-k">return</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">transaction</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-s1">t2</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-c">// 启用 CLS 后,此处的查询默认情况下将使用 t2.</span>
    <span class="pl-c">// 传递 `transaction` 参数以定义/更改它们所属的事务.</span>
    <span class="pl-k">return</span> <span class="pl-v">Promise</span><span class="pl-kos">.</span><span class="pl-en">all</span><span class="pl-kos">(</span><span class="pl-kos">[</span>
        <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'Bob'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">transaction</span>: <span class="pl-c1">null</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
        <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'Mallory'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">transaction</span>: <span class="pl-s1">t1</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
        <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'John'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span> <span class="pl-c">// 这将默认为 t2</span>
    <span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h2><a id="user-content-传递参数" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/transactions.md#%E4%BC%A0%E9%80%92%E5%8F%82%E6%95%B0" aria-hidden="true"></a>传递参数</h2>
<p><code>sequelize.transaction</code>&nbsp;方法接受参数.</p>
<p>对于非托管事务,只需使用&nbsp;<code>sequelize.transaction(options)</code>.</p>
<p>对于托管交易,请使用&nbsp;<code>sequelize.transaction(options, callback)</code>.</p>
<h2><a id="user-content-隔离级别" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/transactions.md#%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB" aria-hidden="true"></a>隔离级别</h2>
<p>启动事务时可能使用的隔离级别：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> Transaction <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'sequelize'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 以下是有效的隔离级别:</span>
<span class="pl-v">Transaction</span><span class="pl-kos">.</span><span class="pl-c1">ISOLATION_LEVELS</span><span class="pl-kos">.</span><span class="pl-c1">READ_UNCOMMITTED</span> <span class="pl-c">// "READ UNCOMMITTED"</span>
<span class="pl-v">Transaction</span><span class="pl-kos">.</span><span class="pl-c1">ISOLATION_LEVELS</span><span class="pl-kos">.</span><span class="pl-c1">READ_COMMITTED</span> <span class="pl-c">// "READ COMMITTED"</span>
<span class="pl-v">Transaction</span><span class="pl-kos">.</span><span class="pl-c1">ISOLATION_LEVELS</span><span class="pl-kos">.</span><span class="pl-c1">REPEATABLE_READ</span>  <span class="pl-c">// "REPEATABLE READ"</span>
<span class="pl-v">Transaction</span><span class="pl-kos">.</span><span class="pl-c1">ISOLATION_LEVELS</span><span class="pl-kos">.</span><span class="pl-c1">SERIALIZABLE</span> <span class="pl-c">// "SERIALIZABLE"</span></pre>
</div>
<p>默认情况下,sequelize 使用数据库的隔离级别. 如果要使用其他隔离级别,请传入所需的级别作为第一个参数：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> Transaction <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'sequelize'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">transaction</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">isolationLevel</span>: <span class="pl-v">Transaction</span><span class="pl-kos">.</span><span class="pl-c1">ISOLATION_LEVELS</span><span class="pl-kos">.</span><span class="pl-c1">SERIALIZABLE</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-s1">t</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-c">// 你的代码</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>你还可以使用 Sequelize 构造函数中的一个参数来全局覆盖&nbsp;<code>isolationLevel</code>&nbsp;设置：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> Sequelize<span class="pl-kos">,</span> Transaction <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'sequelize'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-s">'sqlite::memory:'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">isolationLevel</span>: <span class="pl-v">Transaction</span><span class="pl-kos">.</span><span class="pl-c1">ISOLATION_LEVELS</span><span class="pl-kos">.</span><span class="pl-c1">SERIALIZABLE</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p><strong>MSSQL 注意:</strong>&nbsp;<em>因为指定的&nbsp;<code>isolationLevel</code>&nbsp;被直接传递给&nbsp;<code>tedious&nbsp;</code>,所以没有记录&nbsp;<code>SET ISOLATION LEVEL</code>&nbsp;查询.</em></p>
<h2><a id="user-content-与其他-sequelize-方法一起使用" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/transactions.md#%E4%B8%8E%E5%85%B6%E4%BB%96-sequelize-%E6%96%B9%E6%B3%95%E4%B8%80%E8%B5%B7%E4%BD%BF%E7%94%A8" aria-hidden="true"></a>与其他 sequelize 方法一起使用</h2>
<p><code>transaction</code>&nbsp;参数与大多数其他参数一起使用,通常是方法的第一个参数.</p>
<p>对于带有值的方法,例如&nbsp;<code>.create</code>,<code>.update()</code>&nbsp;等.<code>transaction</code>&nbsp;应该传递给第二个参数.</p>
<p>如果不确定,请参考你使用的方法的 API 文档以确保正确.</p>
<p>示例:</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'Foo Bar'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">transaction</span>: <span class="pl-s1">t</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">name</span>: <span class="pl-s">'Foo Bar'</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">transaction</span>: <span class="pl-s1">t</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h2><a id="user-content-aftercommit-hook" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/transactions.md#aftercommit-hook" aria-hidden="true"></a><code>afterCommit</code>&nbsp;hook</h2>
<p>一个&nbsp;<code>transaction</code>&nbsp;对象允许跟踪它是否以及何时被提交.</p>
<p>可以将&nbsp;<code>afterCommit</code>&nbsp;hook 添加到托管和非托管事务对象中：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-c">// 托管事务:</span>
<span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">transaction</span><span class="pl-kos">(</span><span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-s1">t</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-s1">t</span><span class="pl-kos">.</span><span class="pl-en">afterCommit</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-c">// 你的代码</span>
  <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 非托管事务:</span>
<span class="pl-k">const</span> <span class="pl-s1">t</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">transaction</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-s1">t</span><span class="pl-kos">.</span><span class="pl-en">afterCommit</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-c">// 你的代码</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">await</span> <span class="pl-s1">t</span><span class="pl-kos">.</span><span class="pl-en">commit</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>传递给&nbsp;<code>afterCommit</code>&nbsp;的回调可以是&nbsp;<code>async</code>. 在这种情况下：</p>
<ul>
  <li>对于托管交易：<code>sequelize.transaction</code>&nbsp;调用将在完成之前等待它;</li>
  <li>对于非托管交易：<code>t.commit</code>&nbsp;调用将在完成之前等待它.</li>
</ul>
<p>注意:</p>
<ul>
  <li>如果事务回滚,则不会引发&nbsp;<code>afterCommit</code>&nbsp;hook;</li>
  <li><code>afterCommit</code>&nbsp;hook 不修改事务的返回值(与大多数 hook 不同)</li>
</ul>
<p>你可以将&nbsp;<code>afterCommit</code>&nbsp;hook 与模型 hook 结合使用,以了解何时保存实例并在事务外部可用</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">afterSave</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-s1">instance</span><span class="pl-kos">,</span> <span class="pl-s1">options</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">options</span><span class="pl-kos">.</span><span class="pl-c1">transaction</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-c">// 在事务中保存完成,</span>
    <span class="pl-c">// 等待事务提交以通知侦听器实例已保存</span>
    <span class="pl-s1">options</span><span class="pl-kos">.</span><span class="pl-c1">transaction</span><span class="pl-kos">.</span><span class="pl-en">afterCommit</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-c">/* 通知 */</span><span class="pl-kos">)</span>
    <span class="pl-k">return</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
  <span class="pl-c">// 在事务外保存完成,使调用者可以安全地获取更新的模型</span>
  <span class="pl-c">// 通知</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<h2><a id="user-content-锁" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/transactions.md#%E9%94%81" aria-hidden="true"></a>锁</h2>
<p>可以使用锁执行&nbsp;<code>transaction</code>&nbsp;中的查询：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">return</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">limit</span>: <span class="pl-c1">1</span><span class="pl-kos">,</span>
  <span class="pl-c1">lock</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
  <span class="pl-c1">transaction</span>: <span class="pl-s1">t1</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>事务中的查询可以跳过锁定的行：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">return</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">limit</span>: <span class="pl-c1">1</span><span class="pl-kos">,</span>
  <span class="pl-c1">lock</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
  <span class="pl-c1">skipLocked</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
  <span class="pl-c1">transaction</span>: <span class="pl-s1">t2</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;<br /><br /></span></pre>
  <h1>Hooks - 钩子</h1>
  <p>Hooks(也称为生命周期事件)是在执行 sequelize 中的调用之前和之后调用的函数. 例如,如果要在保存之前始终在模型上设置一个值,则可以添加一个&nbsp;<code>beforeUpdate</code>&nbsp;hook.</p>
  <p><strong>注意:</strong>&nbsp;<em>你不能对实例使用 hook. Hook 用于模型.</em></p>
  <h2>可用的 hooks</h2>
  <p>Sequelize 提供了很多 hook. 完整列表可以直接在<a href="https://github.com/sequelize/sequelize/blob/master/lib/hooks.js#L7">源代码 - lib/hooks.js</a>&nbsp;中找到.</p>
  <h2>Hooks 触发顺序</h2>
  <p>下面显示了最常见的 hook 的触发顺序.</p>
  <p><em><strong>注意:</strong>&nbsp;此列表并不详尽.</em></p>
  <pre lang="text"><code>(1)
  beforeBulkCreate(instances, options)
  beforeBulkDestroy(options)
  beforeBulkUpdate(options)
(2)
  beforeValidate(instance, options)

[... validation happens ...]

(3)
  afterValidate(instance, options)
  validationFailed(instance, options, error)
(4)
  beforeCreate(instance, options)
  beforeDestroy(instance, options)
  beforeUpdate(instance, options)
  beforeSave(instance, options)
  beforeUpsert(values, options)

[... creation/update/destruction happens ...]

(5)
  afterCreate(instance, options)
  afterDestroy(instance, options)
  afterUpdate(instance, options)
  afterSave(instance, options)
  afterUpsert(created, options)
(6)
  afterBulkCreate(instances, options)
  afterBulkDestroy(options)
  afterBulkUpdate(options)
</code></pre>
  <h2>声明 Hooks</h2>
  <p>Hook 的参数通过引用传递. 这意味着你可以更改值,这将反映在 insert / update 语句中. 一个 hook 可能包含异步动作 - 在这种情况下,hook 函数应该返回一个 Promise.</p>
  <p>当前有三种方法以编程方式添加 hook：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 方法 1 通过 .init() 方法</span>
<span class="pl-k">class</span> <span class="pl-v">User</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">username</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">mood</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">ENUM</span><span class="pl-kos">,</span>
    <span class="pl-c1">values</span>: <span class="pl-kos">[</span><span class="pl-s">'happy'</span><span class="pl-kos">,</span> <span class="pl-s">'sad'</span><span class="pl-kos">,</span> <span class="pl-s">'neutral'</span><span class="pl-kos">]</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">hooks</span>: <span class="pl-kos">{</span>
    <span class="pl-en">beforeValidate</span>: <span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">,</span> <span class="pl-s1">options</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
      <span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-c1">mood</span> <span class="pl-c1">=</span> <span class="pl-s">'happy'</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-en">afterValidate</span>: <span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">,</span> <span class="pl-s1">options</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
      <span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-c1">username</span> <span class="pl-c1">=</span> <span class="pl-s">'Toni'</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  sequelize
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 方法 2 通过 .addHook() 方法</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">addHook</span><span class="pl-kos">(</span><span class="pl-s">'beforeValidate'</span><span class="pl-kos">,</span> <span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">,</span> <span class="pl-s1">options</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-c1">mood</span> <span class="pl-c1">=</span> <span class="pl-s">'happy'</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">addHook</span><span class="pl-kos">(</span><span class="pl-s">'afterValidate'</span><span class="pl-kos">,</span> <span class="pl-s">'someCustomName'</span><span class="pl-kos">,</span> <span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">,</span> <span class="pl-s1">options</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-k">return</span> <span class="pl-v">Promise</span><span class="pl-kos">.</span><span class="pl-en">reject</span><span class="pl-kos">(</span><span class="pl-k">new</span> <span class="pl-v">Error</span><span class="pl-kos">(</span><span class="pl-s">"I'm afraid I can't let you do that!"</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 方法 3 通过 direct 方法</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">beforeCreate</span><span class="pl-kos">(</span><span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">,</span> <span class="pl-s1">options</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-k">const</span> <span class="pl-s1">hashedPassword</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-en">hashPassword</span><span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-c1">password</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-c1">password</span> <span class="pl-c1">=</span> <span class="pl-s1">hashedPassword</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">afterValidate</span><span class="pl-kos">(</span><span class="pl-s">'myHookAfter'</span><span class="pl-kos">,</span> <span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">,</span> <span class="pl-s1">options</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-c1">username</span> <span class="pl-c1">=</span> <span class="pl-s">'Toni'</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h2>删除 hooks</h2>
  <p>只能删除带有名称参数的 hook.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">class</span> <span class="pl-v">Book</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">Book</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">title</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> sequelize <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-v">Book</span><span class="pl-kos">.</span><span class="pl-en">addHook</span><span class="pl-kos">(</span><span class="pl-s">'afterCreate'</span><span class="pl-kos">,</span> <span class="pl-s">'notifyUsers'</span><span class="pl-kos">,</span> <span class="pl-kos">(</span><span class="pl-s1">book</span><span class="pl-kos">,</span> <span class="pl-s1">options</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-c">// ...</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-v">Book</span><span class="pl-kos">.</span><span class="pl-en">removeHook</span><span class="pl-kos">(</span><span class="pl-s">'afterCreate'</span><span class="pl-kos">,</span> <span class="pl-s">'notifyUsers'</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>你可以有许多同名的 hook. 调用&nbsp;<code>.removeHook()</code>&nbsp;将删除所有对象.</p>
  <h2>全局 / 通用 hooks</h2>
  <p>全局 hook 是所有模型运行的 hook. 他们可以为所有模型定义所需的行为,对于插件特别有用. 可以用两种方式定义它们,它们的语义略有不同：</p>
  <h3>默认 Hooks (在 Sequelize 构造函数参数)</h3>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span>...<span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">define</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">hooks</span>: <span class="pl-kos">{</span>
      <span class="pl-en">beforeCreate</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-c">// 做点什么</span>
      <span class="pl-kos">}</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>这会向所有模型添加一个默认 hook,如果模型未定义自己的&nbsp;<code>beforeCreate</code>&nbsp;hook,则将运行该 hook：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">User</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'User'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span><span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Project</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'Project'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span><span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">hooks</span>: <span class="pl-kos">{</span>
    <span class="pl-en">beforeCreate</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-c">// 做点其他事</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span><span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>    <span class="pl-c">// 运行全局 hook</span>
<span class="pl-k">await</span> <span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span><span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 运行自己的 hook (因为全局 hook 被覆盖)</span></pre>
  </div>
  <h3>常驻 Hooks (通过&nbsp;<code>sequelize.addHook</code>)</h3>
  <div class="highlight highlight-source-js">
<pre><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">addHook</span><span class="pl-kos">(</span><span class="pl-s">'beforeCreate'</span><span class="pl-kos">,</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-c">// 做点什么</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>无论模型是否指定自己的&nbsp;<code>beforeCreate</code>&nbsp;hook,该 hook 始终运行. 本地 hook 总是在全局 hook 之前运行：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">User</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'User'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span><span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Project</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'Project'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span><span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">hooks</span>: <span class="pl-kos">{</span>
    <span class="pl-en">beforeCreate</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-c">// 做点其他事</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span><span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>    <span class="pl-c">// 运行全局 hook</span>
<span class="pl-k">await</span> <span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span><span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 运行自己的 hook, 其次是全局 hook</span></pre>
  </div>
  <p>也可以在传递给 Sequelize 构造函数的参数中定义常驻 hook：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span>...<span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">hooks</span>: <span class="pl-kos">{</span>
    <span class="pl-en">beforeCreate</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-c">// 做点什么</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>请注意,以上内容与上述&nbsp;<em>默认 Hooks</em>&nbsp;不同. 那就是使用构造函数的&nbsp;<code>define</code>&nbsp;参数. 这里不是.</p>
  <h3>连接 Hooks</h3>
  <p>Sequelize 提供了四个 hook,它们在获得或释放数据库连接之前和之后立即执行：</p>
  <ul>
    <li><code>sequelize.beforeConnect(callback)</code>
      <ul>
        <li>回调具有以下形式&nbsp;<code>async (config) =&gt; /* ... */</code></li>
      </ul>
    </li>
    <li><code>sequelize.afterConnect(callback)</code>
      <ul>
        <li>回调具有以下形式&nbsp;<code>async (connection, config) =&gt; /* ... */</code></li>
      </ul>
    </li>
    <li><code>sequelize.beforeDisconnect(callback)</code>
      <ul>
        <li>回调具有以下形式&nbsp;<code>async (connection) =&gt; /* ... */</code></li>
      </ul>
    </li>
    <li><code>sequelize.afterDisconnect(callback)</code>
      <ul>
        <li>回调具有以下形式&nbsp;<code>async (connection) =&gt; /* ... */</code></li>
      </ul>
    </li>
  </ul>
  <p>如果你需要异步获取数据库凭据,或者需要在创建低级数据库连接后直接访问它,这些 hook 很有用.</p>
  <p>例如,我们可以从令牌存储异步获取数据库密码,并使用新的凭证对 Sequelize 的配置对象进行更新：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">beforeConnect</span><span class="pl-kos">(</span><span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-s1">config</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-s1">config</span><span class="pl-kos">.</span><span class="pl-c1">password</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-en">getAuthToken</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>这些 hook 只能&nbsp;<em>被</em>&nbsp;声明为永久全局 hook,因为所有模型都共享连接池.</p>
  <h2>实例 hooks</h2>
  <p>每当你编辑单个对象时,都会触发以下 hook：</p>
  <ul>
    <li><code>beforeValidate</code></li>
    <li><code>afterValidate</code>&nbsp;/&nbsp;<code>validationFailed</code></li>
    <li><code>beforeCreate</code>&nbsp;/&nbsp;<code>beforeUpdate</code>&nbsp;/&nbsp;<code>beforeSave</code>&nbsp;/&nbsp;<code>beforeDestroy</code></li>
    <li><code>afterCreate</code>&nbsp;/&nbsp;<code>afterUpdate</code>&nbsp;/&nbsp;<code>afterSave</code>&nbsp;/&nbsp;<code>afterDestroy</code></li>
  </ul>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">beforeCreate</span><span class="pl-kos">(</span><span class="pl-s1">user</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-c1">accessLevel</span> <span class="pl-c1">&gt;</span> <span class="pl-c1">10</span> <span class="pl-c1">&amp;&amp;</span> <span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-c1">username</span> !== <span class="pl-s">"Boss"</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-v">Error</span><span class="pl-kos">(</span><span class="pl-s">"You can't grant this user an access level above 10!"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>以下示例将引发错误:</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">try</span> <span class="pl-kos">{</span>
  <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">username</span>: <span class="pl-s">'Not a Boss'</span><span class="pl-kos">,</span> <span class="pl-c1">accessLevel</span>: <span class="pl-c1">20</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span> <span class="pl-k">catch</span> <span class="pl-kos">(</span><span class="pl-s1">error</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">error</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 你不能授予该用户10以上的访问权限！</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span></pre>
  </div>
  <p>以下示例将成功:</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">user</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">username</span>: <span class="pl-s">'Boss'</span><span class="pl-kos">,</span> <span class="pl-c1">accessLevel</span>: <span class="pl-c1">20</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 用户对象,用户名 `Boss`,accessLevel 为 20</span></pre>
  </div>
  <h3>模型 hooks</h3>
  <p>有时你会使用诸如&nbsp;<code>bulkCreate</code>,&nbsp;<code>update</code>&nbsp;和&nbsp;<code>destroy</code>&nbsp;之类的方法一次编辑多个记录. 每当你使用这些方法之一时,就会触发以下 hook：</p>
  <ul>
    <li><code>YourModel.beforeBulkCreate(callback)</code>
      <ul>
        <li>回调具有以下形式&nbsp;<code>(instances, options) =&gt; /* ... */</code></li>
      </ul>
    </li>
    <li><code>YourModel.beforeBulkUpdate(callback)</code>
      <ul>
        <li>回调具有以下形式&nbsp;<code>(options) =&gt; /* ... */</code></li>
      </ul>
    </li>
    <li><code>YourModel.beforeBulkDestroy(callback)</code>
      <ul>
        <li>回调具有以下形式&nbsp;<code>(options) =&gt; /* ... */</code></li>
      </ul>
    </li>
    <li><code>YourModel.afterBulkCreate(callback)</code>
      <ul>
        <li>回调具有以下形式&nbsp;<code>(instances, options) =&gt; /* ... */</code></li>
      </ul>
    </li>
    <li><code>YourModel.afterBulkUpdate(callback)</code>
      <ul>
        <li>回调具有以下形式&nbsp;<code>(options) =&gt; /* ... */</code></li>
      </ul>
    </li>
    <li><code>YourModel.afterBulkDestroy(callback)</code>
      <ul>
        <li>回调具有以下形式&nbsp;<code>(options) =&gt; /* ... */</code></li>
      </ul>
    </li>
  </ul>
  <p>注意：默认情况下,类似&nbsp;<code>bulkCreate</code>&nbsp;的方法不会触发单独的 hook - 仅批量 hook. 但是,如果你还希望触发单个 hook,则可以将&nbsp;<code>{ individualHooks: true }</code>&nbsp;参数传递给查询调用. 但是,这可能会严重影响性能,具体取决于所涉及的记录数(因为,除其他外,所有实例都将被加载到内存中). 例子：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">await</span> <span class="pl-v">Model</span><span class="pl-kos">.</span><span class="pl-en">destroy</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span> <span class="pl-c1">accessLevel</span>: <span class="pl-c1">0</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">individualHooks</span>: <span class="pl-c1">true</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 这将选择所有将要删除的记录,并在每个实例上触发 `beforeDestroy` 和 `afterDestroy`.</span>

<span class="pl-k">await</span> <span class="pl-v">Model</span><span class="pl-kos">.</span><span class="pl-en">update</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">username</span>: <span class="pl-s">'Tony'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span> <span class="pl-c1">accessLevel</span>: <span class="pl-c1">0</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">individualHooks</span>: <span class="pl-c1">true</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 这将选择所有将要更新的记录,并在每个实例上发出 `beforeUpdate` 和 `afterUpdate`.</span></pre>
  </div>
  <p>如果你将&nbsp;<code>Model.bulkCreate(...)</code>&nbsp;与&nbsp;<code>updateOnDuplicate</code>&nbsp;参数一起使用,则对 hook 中对&nbsp;<code>updateOnDuplicate</code>&nbsp;数组中未提供的字段所做的更改将不会保留到数据库中. 但是,如果需要的话,可以在挂钩中更改&nbsp;<code>updateOnDuplicate</code>&nbsp;参数.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">beforeBulkCreate</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-s1">users</span><span class="pl-kos">,</span> <span class="pl-s1">options</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-k">for</span> <span class="pl-kos">(</span><span class="pl-k">const</span> <span class="pl-s1">user</span> <span class="pl-k">of</span> <span class="pl-s1">users</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-c1">isMember</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-c1">memberSince</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Date</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>

  <span class="pl-c">// 将 `memberSince` 添加到 updateOnDuplicate,否则它将不会持久化</span>
  <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">options</span><span class="pl-kos">.</span><span class="pl-c1">updateOnDuplicate</span> <span class="pl-c1">&amp;&amp;</span> !<span class="pl-s1">options</span><span class="pl-kos">.</span><span class="pl-c1">updateOnDuplicate</span><span class="pl-kos">.</span><span class="pl-en">includes</span><span class="pl-kos">(</span><span class="pl-s">'memberSince'</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-s1">options</span><span class="pl-kos">.</span><span class="pl-c1">updateOnDuplicate</span><span class="pl-kos">.</span><span class="pl-en">push</span><span class="pl-kos">(</span><span class="pl-s">'memberSince'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 使用 updateOnDuplicate 参数批量更新现有用户</span>
<span class="pl-k">await</span> <span class="pl-v">Users</span><span class="pl-kos">.</span><span class="pl-en">bulkCreate</span><span class="pl-kos">(</span><span class="pl-kos">[</span>
  <span class="pl-kos">{</span> <span class="pl-c1">id</span>: <span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">isMember</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-kos">{</span> <span class="pl-c1">id</span>: <span class="pl-c1">2</span><span class="pl-kos">,</span> <span class="pl-c1">isMember</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span>
<span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">updateOnDuplicate</span>: <span class="pl-kos">[</span><span class="pl-s">'isMember'</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h2>关联</h2>
  <p>在大多数情况下,hook 在关联时对实例的作用相同.</p>
  <h3>一对一和一对多关联</h3>
  <ul>
    <li>
      <p>当使用&nbsp;<code>add</code>/<code>set</code>&nbsp;mixin 方法时,<code>beforeUpdate</code>&nbsp;和&nbsp;<code>afterUpdate</code>&nbsp;hook 将运行.</p>
    </li>
    <li>
      <p><code>beforeDestroy</code>&nbsp;和&nbsp;<code>afterDestroy</code>&nbsp;hook 只会在具有&nbsp;<code>onDelete: 'CASCADE'</code>&nbsp;和&nbsp;<code>hooks: true</code>&nbsp;的关联上被调用. 例如</p>
    </li>
  </ul>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">class</span> <span class="pl-v">Projects</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">Projects</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">title</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> sequelize <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">class</span> <span class="pl-v">Tasks</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">Tasks</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">title</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> sequelize <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-v">Projects</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Tasks</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">onDelete</span>: <span class="pl-s">'CASCADE'</span><span class="pl-kos">,</span> <span class="pl-c1">hooks</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Tasks</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Projects</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>该代码将在 Tasks 模型上运行&nbsp;<code>beforeDestroy</code>&nbsp;和&nbsp;<code>afterDestroy</code>&nbsp;hook.</p>
  <p>默认情况下,Sequelize 将尝试尽可能优化你的查询. 当在删除时调用级联时,Sequelize 将简单地执行：</p>
  <div class="highlight highlight-source-sql">
    <pre><span class="pl-k">DELETE</span> <span class="pl-k">FROM</span> <span class="pl-s"><span class="pl-pds">`</span>table<span class="pl-pds">`</span></span> <span class="pl-k">WHERE</span> associatedIdentifier <span class="pl-k">=</span> <span class="pl-c1">associatedIdentifier</span>.<span class="pl-c1">primaryKey</span></pre>
  </div>
  <p>但是,添加&nbsp;<code>hooks: true</code>&nbsp;会明确告诉 Sequelize 优化与你无关. 然后,Sequelize 首先将对关联的对象执行&nbsp;<code>SELECT</code>&nbsp;并逐个销毁每个实例,以便能够正确调用 hook(使用正确的参数).</p>
  <h3>多对多关联</h3>
  <ul>
    <li>
      <p>当对&nbsp;<code>belongsToMany</code>&nbsp;关系使用&nbsp;<code>add</code>&nbsp;mixin 方法时(将一个或多个记录添加到联结表中),联结模型中的&nbsp;<code>beforeBulkCreate</code>&nbsp;和&nbsp;<code>afterBulkCreate</code>hook 将运行.</p>
      <ul>
        <li>如果将&nbsp;<code>{ individualHooks: true }</code>&nbsp;传递给该调用,则每个单独的 hook 也将运行.</li>
      </ul>
    </li>
    <li>
      <p>当对&nbsp;<code>belongsToMany</code>&nbsp;关系使用&nbsp;<code>remove</code>&nbsp;mixin 方法时(将一个或多个记录删除到联结表中),联结模型中的&nbsp;<code>beforeBulkDestroy</code>&nbsp;和&nbsp;<code>afterBulkDestroy</code>&nbsp;hook 将运行.</p>
      <ul>
        <li>如果将&nbsp;<code>{ individualHooks: true }</code>&nbsp;传递给该调用,则每个单独的 hook 也将运行.</li>
      </ul>
    </li>
  </ul>
  <p>如果你的关联是多对多,则在使用&nbsp;<code>remove</code>&nbsp;调用时,你可能会对在直通模型上触发 hook 感兴趣. 在内部,sequelize 使用的是&nbsp;<code>Model.destroy</code>,从而导致在每个直通实例上调用&nbsp;<code>bulkDestroy</code>&nbsp;而不是&nbsp;<code>before/afterDestroy</code>&nbsp;hook.</p>
  <h2>Hooks 和 事务</h2>
  <p>Sequelize 中的许多模型操作都允许你在方法的 options 参数中指定事务. 如果在原始调用中指定了事务,则该事务将出现在传递给 hook 函数的 options 参数中. 例如,考虑以下代码片段：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">addHook</span><span class="pl-kos">(</span><span class="pl-s">'afterCreate'</span><span class="pl-kos">,</span> <span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-s1">user</span><span class="pl-kos">,</span> <span class="pl-s1">options</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-c">// 我们可以使用 `options.transaction` 来执行</span>
  <span class="pl-c">// 与触发此 hook 的调用相同的事务来执行其他一些调用</span>
  <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">update</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">mood</span>: <span class="pl-s">'sad'</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
    <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">id</span>: <span class="pl-s1">user</span><span class="pl-kos">.</span><span class="pl-c1">id</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-c1">transaction</span>: <span class="pl-s1">options</span><span class="pl-kos">.</span><span class="pl-c1">transaction</span>
  <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">await</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">transaction</span><span class="pl-kos">(</span><span class="pl-k">async</span> <span class="pl-s1">t</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
    <span class="pl-c1">username</span>: <span class="pl-s">'someguy'</span><span class="pl-kos">,</span>
    <span class="pl-c1">mood</span>: <span class="pl-s">'happy'</span><span class="pl-kos">,</span>
    <span class="pl-c1">transaction</span>: <span class="pl-s1">t</span>
  <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>如果在前面的代码中对&nbsp;<code>User.update</code>&nbsp;的调用中未包含 transaction 参数,则不会发生更改,因为在提交未决事务之前,数据库中不存在我们新创建的用户.</p>
  <h3>内部事务</h3>
  <p>重要的是要认识到,sequelize 可能会在内部对某些操作(例如<code>Model.findOrCreate</code>)使用事务. 如果 hook 函数执行依赖于数据库中对象存在的读取或写入操作,或者像上一节中的示例一样修改对象的存储值,则应始终指定<code>{transaction：options.transaction}</code>：</p>
  <ul>
    <li>如果使用了事务,则&nbsp;<code>{transaction：options.transaction}</code>&nbsp;将确保再次使用该事务;</li>
    <li>否则,<code>{ transaction: options.transaction }</code>&nbsp;等同于&nbsp;<code>{ transaction: undefined }</code>,这将不使用事务.</li>
  </ul>
  <p>这样,你的 hook 将始终正确运行.</p>
  <pre><span class="pl-kos">&nbsp;</span></pre>
  <h1>Query Interface - 查询接口</h1>
  <p>Sequelize 实例使用一种称为&nbsp;<strong>查询接口</strong>&nbsp;的东西来以与方言无关的方式与数据库进行通信. 你在本手册中学到的大多数方法都是通过查询接口中的几种方法来实现的.</p>
  <p>因此,查询接口中的方法是较低级的方法; 仅当找不到其他方法来使用 Sequelize 的高级 API 时,才应使用它们. 当然,它们比直接运行原始查询(即,手工编写SQL)的级别更高.</p>
  <p>本指南展示了一些示例,但是要获取其功能的完整列表以及每种方法的详细用法,请查看<a href="https://sequelize.org/master/class/lib/dialects/abstract/query-interface.js~QueryInterface.html" rel="nofollow">查询接口 API</a>.</p>
  <h2>获取查询界面</h2>
  <p>从现在开始,我们将&nbsp;<code>queryInterface</code>&nbsp;称为&nbsp;<a href="https://sequelize.org/master/class/lib/dialects/abstract/query-interface.js~QueryInterface.html" rel="nofollow">查询接口</a>&nbsp;类的单例实例,该实例可在你的 Sequelize 实例上使用：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> Sequelize<span class="pl-kos">,</span> DataTypes <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'sequelize'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-c">/* ... */</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">queryInterface</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">getQueryInterface</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h2>创建一个表</h2>
  <div class="highlight highlight-source-js">
<pre><span class="pl-s1">queryInterface</span><span class="pl-kos">.</span><span class="pl-en">createTable</span><span class="pl-kos">(</span><span class="pl-s">'Person'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">isBetaMember</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">BOOLEAN</span><span class="pl-kos">,</span>
    <span class="pl-c1">defaultValue</span>: <span class="pl-c1">false</span><span class="pl-kos">,</span>
    <span class="pl-c1">allowNull</span>: <span class="pl-c1">false</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>生成 SQL (使用 SQLite):</p>
  <div class="highlight highlight-source-sql">
<pre><span class="pl-k">CREATE</span> <span class="pl-k">TABLE</span> <span class="pl-en">IF</span> NOT EXISTS <span class="pl-s"><span class="pl-pds">`</span>Person<span class="pl-pds">`</span></span> (
  <span class="pl-s"><span class="pl-pds">`</span>name<span class="pl-pds">`</span></span> <span class="pl-k">VARCHAR</span>(<span class="pl-c1">255</span>),
  <span class="pl-s"><span class="pl-pds">`</span>isBetaMember<span class="pl-pds">`</span></span> <span class="pl-k">TINYINT</span>(<span class="pl-c1">1</span>) <span class="pl-k">NOT NULL</span> DEFAULT <span class="pl-c1">0</span>
);</pre>
  </div>
  <p><strong>注意:</strong>&nbsp;考虑定义一个模型,然后调用&nbsp;<code>YourModel.sync()</code>,这是一个较高级别的方法.</p>
  <h2>向表添加列</h2>
  <div class="highlight highlight-source-js">
    <pre><span class="pl-s1">queryInterface</span><span class="pl-kos">.</span><span class="pl-en">addColumn</span><span class="pl-kos">(</span><span class="pl-s">'Person'</span><span class="pl-kos">,</span> <span class="pl-s">'petName'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>生成 SQL (使用 SQLite):</p>
  <div class="highlight highlight-source-sql">
    <pre><span class="pl-k">ALTER</span> <span class="pl-k">TABLE</span> <span class="pl-s"><span class="pl-pds">`</span>Person<span class="pl-pds">`</span></span> ADD <span class="pl-s"><span class="pl-pds">`</span>petName<span class="pl-pds">`</span></span> <span class="pl-k">VARCHAR</span>(<span class="pl-c1">255</span>);</pre>
  </div>
  <h2>更改列的数据类型</h2>
  <div class="highlight highlight-source-js">
<pre><span class="pl-s1">queryInterface</span><span class="pl-kos">.</span><span class="pl-en">changeColumn</span><span class="pl-kos">(</span><span class="pl-s">'Person'</span><span class="pl-kos">,</span> <span class="pl-s">'foo'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">FLOAT</span><span class="pl-kos">,</span>
  <span class="pl-c1">defaultValue</span>: <span class="pl-c1">3.14</span><span class="pl-kos">,</span>
  <span class="pl-c1">allowNull</span>: <span class="pl-c1">false</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>生成 SQL (使用 MySQL):</p>
  <div class="highlight highlight-source-sql">
    <pre><span class="pl-k">ALTER</span> <span class="pl-k">TABLE</span> <span class="pl-s"><span class="pl-pds">`</span>Person<span class="pl-pds">`</span></span> CHANGE <span class="pl-s"><span class="pl-pds">`</span>foo<span class="pl-pds">`</span></span> <span class="pl-s"><span class="pl-pds">`</span>foo<span class="pl-pds">`</span></span> FLOAT <span class="pl-k">NOT NULL</span> DEFAULT <span class="pl-c1">3</span>.<span class="pl-c1">14</span>;</pre>
  </div>
  <h2>删除列</h2>
  <div class="highlight highlight-source-js">
    <pre><span class="pl-s1">queryInterface</span><span class="pl-kos">.</span><span class="pl-en">removeColumn</span><span class="pl-kos">(</span><span class="pl-s">'Person'</span><span class="pl-kos">,</span> <span class="pl-s">'petName'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c">/* 查询参数 */</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>生成 SQL (使用 PostgreSQL):</p>
  <div class="highlight highlight-source-sql">
    <pre><span class="pl-k">ALTER</span> <span class="pl-k">TABLE</span> <span class="pl-s"><span class="pl-pds">"</span>public<span class="pl-pds">"</span></span>.<span class="pl-s"><span class="pl-pds">"</span>Person<span class="pl-pds">"</span></span> DROP COLUMN <span class="pl-s"><span class="pl-pds">"</span>petName<span class="pl-pds">"</span></span>;</pre>
  </div>
  <h2>更改和删除 SQLite 中的列</h2>
  <p>SQLite 不支持直接更改和删除列. 但是,Sequelize 将通过受<a href="https://www.sqlite.org/lang_altertable.html#otheralter" rel="nofollow">这些说明</a>的启发在备份表的帮助下重新创建整个表,以解决此问题.</p>
  <p>示例:</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 假设我们在 SQLite 中创建了一个表,如下所示:</span>
<span class="pl-s1">queryInterface</span><span class="pl-kos">.</span><span class="pl-en">createTable</span><span class="pl-kos">(</span><span class="pl-s">'Person'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">isBetaMember</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">BOOLEAN</span><span class="pl-kos">,</span>
    <span class="pl-c1">defaultValue</span>: <span class="pl-c1">false</span><span class="pl-kos">,</span>
    <span class="pl-c1">allowNull</span>: <span class="pl-c1">false</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">petName</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">foo</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 我们改变一列:</span>
<span class="pl-s1">queryInterface</span><span class="pl-kos">.</span><span class="pl-en">changeColumn</span><span class="pl-kos">(</span><span class="pl-s">'Person'</span><span class="pl-kos">,</span> <span class="pl-s">'foo'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">FLOAT</span><span class="pl-kos">,</span>
  <span class="pl-c1">defaultValue</span>: <span class="pl-c1">3.14</span><span class="pl-kos">,</span>
  <span class="pl-c1">allowNull</span>: <span class="pl-c1">false</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>为 SQLite 生成了以下 SQL 调用:</p>
  <div class="highlight highlight-source-sql">
<pre>PRAGMA TABLE_INFO(<span class="pl-s"><span class="pl-pds">`</span>Person<span class="pl-pds">`</span></span>);

<span class="pl-k">CREATE</span> <span class="pl-k">TABLE</span> <span class="pl-en">IF</span> NOT EXISTS <span class="pl-s"><span class="pl-pds">`</span>Person_backup<span class="pl-pds">`</span></span> (
  <span class="pl-s"><span class="pl-pds">`</span>name<span class="pl-pds">`</span></span> <span class="pl-k">VARCHAR</span>(<span class="pl-c1">255</span>),
  <span class="pl-s"><span class="pl-pds">`</span>isBetaMember<span class="pl-pds">`</span></span> <span class="pl-k">TINYINT</span>(<span class="pl-c1">1</span>) <span class="pl-k">NOT NULL</span> DEFAULT <span class="pl-c1">0</span>,
  <span class="pl-s"><span class="pl-pds">`</span>foo<span class="pl-pds">`</span></span> FLOAT <span class="pl-k">NOT NULL</span> DEFAULT <span class="pl-s"><span class="pl-pds">'</span>3.14<span class="pl-pds">'</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>petName<span class="pl-pds">`</span></span> <span class="pl-k">VARCHAR</span>(<span class="pl-c1">255</span>)
);

<span class="pl-k">INSERT INTO</span> <span class="pl-s"><span class="pl-pds">`</span>Person_backup<span class="pl-pds">`</span></span>
  <span class="pl-k">SELECT</span>
    <span class="pl-s"><span class="pl-pds">`</span>name<span class="pl-pds">`</span></span>,
    <span class="pl-s"><span class="pl-pds">`</span>isBetaMember<span class="pl-pds">`</span></span>,
    <span class="pl-s"><span class="pl-pds">`</span>foo<span class="pl-pds">`</span></span>,
    <span class="pl-s"><span class="pl-pds">`</span>petName<span class="pl-pds">`</span></span>
  <span class="pl-k">FROM</span> <span class="pl-s"><span class="pl-pds">`</span>Person<span class="pl-pds">`</span></span>;

<span class="pl-k">DROP</span> <span class="pl-k">TABLE</span> <span class="pl-s"><span class="pl-pds">`</span>Person<span class="pl-pds">`</span></span>;

<span class="pl-k">CREATE</span> <span class="pl-k">TABLE</span> <span class="pl-en">IF</span> NOT EXISTS <span class="pl-s"><span class="pl-pds">`</span>Person<span class="pl-pds">`</span></span> (
  <span class="pl-s"><span class="pl-pds">`</span>name<span class="pl-pds">`</span></span> <span class="pl-k">VARCHAR</span>(<span class="pl-c1">255</span>),
  <span class="pl-s"><span class="pl-pds">`</span>isBetaMember<span class="pl-pds">`</span></span> <span class="pl-k">TINYINT</span>(<span class="pl-c1">1</span>) <span class="pl-k">NOT NULL</span> DEFAULT <span class="pl-c1">0</span>,
  <span class="pl-s"><span class="pl-pds">`</span>foo<span class="pl-pds">`</span></span> FLOAT <span class="pl-k">NOT NULL</span> DEFAULT <span class="pl-s"><span class="pl-pds">'</span>3.14<span class="pl-pds">'</span></span>,
  <span class="pl-s"><span class="pl-pds">`</span>petName<span class="pl-pds">`</span></span> <span class="pl-k">VARCHAR</span>(<span class="pl-c1">255</span>)
);

<span class="pl-k">INSERT INTO</span> <span class="pl-s"><span class="pl-pds">`</span>Person<span class="pl-pds">`</span></span>
  <span class="pl-k">SELECT</span>
    <span class="pl-s"><span class="pl-pds">`</span>name<span class="pl-pds">`</span></span>,
    <span class="pl-s"><span class="pl-pds">`</span>isBetaMember<span class="pl-pds">`</span></span>,
    <span class="pl-s"><span class="pl-pds">`</span>foo<span class="pl-pds">`</span></span>,
    <span class="pl-s"><span class="pl-pds">`</span>petName<span class="pl-pds">`</span></span>
  <span class="pl-k">FROM</span> <span class="pl-s"><span class="pl-pds">`</span>Person_backup<span class="pl-pds">`</span></span>;

<span class="pl-k">DROP</span> <span class="pl-k">TABLE</span> <span class="pl-s"><span class="pl-pds">`</span>Person_backup<span class="pl-pds">`</span></span>;</pre>
  </div>
  <h2>其它</h2>
  <p>如本指南开头所述,Sequelize 中的查询接口还有很多！ 查看&nbsp;<a href="https://sequelize.org/master/class/lib/dialects/abstract/query-interface.js~QueryInterface.html" rel="nofollow">查询接口 API</a>,以获取可以完成的操作的完整列表.</p>
  <pre><span class="pl-kos">&nbsp;</span></pre>
  <h1>Naming Strategies - 命名策略</h1>
  <h2><code>underscored</code>&nbsp;参数</h2>
  <p>Sequelize 为模型提供了&nbsp;<code>underscored</code>&nbsp;参数. 设为&nbsp;<code>true</code>&nbsp;时,此参数会将所有属性的&nbsp;<code>field</code>&nbsp;参数设置为其名称的&nbsp;<a href="https://en.wikipedia.org/wiki/Snake_case" rel="nofollow">snake_case</a>&nbsp;版本. 这也适用于由关联和其他自动生成的字段自动生成的外键. 例：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">User</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'task'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">username</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">underscored</span>: <span class="pl-c1">true</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Task</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'task'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">title</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">underscored</span>: <span class="pl-c1">true</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Task</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Task</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">User</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>上面我们有模型 User 和 Task,都使用了&nbsp;<code>underscored</code>&nbsp;的参数. 他们之间也有一对多的关系. 另外,回想一下,由于默认情况下&nbsp;<code>timestamps</code>&nbsp;为&nbsp;<code>true</code>,因此我们应该期望&nbsp;<code>createedAt</code>&nbsp;和&nbsp;<code>updatedAt</code>&nbsp;字段也将自动创建.</p>
  <p>如果没有&nbsp;<code>underscored</code>&nbsp;参数,Sequelize 会自动定义：</p>
  <ul>
    <li>每个模型的&nbsp;<code>createdAt</code>&nbsp;属性,指向每个表中名为&nbsp;<code>createdAt</code>&nbsp;的列</li>
    <li>每个模型的&nbsp;<code>updatedAt</code>&nbsp;属性,指向每个表中名为&nbsp;<code>updatedAt</code>&nbsp;的列</li>
    <li><code>Task</code>&nbsp;模型中的&nbsp;<code>userId</code>&nbsp;属性,指向任务表中名为&nbsp;<code>userId</code>&nbsp;的列</li>
  </ul>
  <p>启用&nbsp;<code>underscored</code>&nbsp;参数后,Sequelize 将改为定义：</p>
  <ul>
    <li>每个模型的&nbsp;<code>createdAt</code>&nbsp;属性,指向每个表中名为&nbsp;<code>created_at&nbsp;</code>的列</li>
    <li>每个模型的&nbsp;<code>updatedAt</code>&nbsp;属性,指向每个表中名为&nbsp;<code>updated_at&nbsp;</code>的列</li>
    <li><code>Task</code>&nbsp;模型中的&nbsp;<code>userId</code>&nbsp;属性,指向任务表中名为&nbsp;<code>user_id&nbsp;</code>的列</li>
  </ul>
  <p>请注意,在这两种情况下,JavaScript 字段均仍为&nbsp;<a href="https://en.wikipedia.org/wiki/Camel_case" rel="nofollow">camelCase</a>; 此参数仅更改这些字段如何映射到数据库本身. 每个属性的&nbsp;<code>field</code>&nbsp;参数都设置为它们的 snake_case 版本,但属性本身仍为 camelCase.</p>
  <p>这样,在上面的代码上调用&nbsp;<code>sync()</code>&nbsp;将会生成以下内容：</p>
  <div class="highlight highlight-source-sql">
<pre><span class="pl-k">CREATE</span> <span class="pl-k">TABLE</span> <span class="pl-en">IF</span> NOT EXISTS <span class="pl-s"><span class="pl-pds">"</span>users<span class="pl-pds">"</span></span> (
  <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span> <span class="pl-k">SERIAL</span>,
  <span class="pl-s"><span class="pl-pds">"</span>username<span class="pl-pds">"</span></span> <span class="pl-k">VARCHAR</span>(<span class="pl-c1">255</span>),
  <span class="pl-s"><span class="pl-pds">"</span>created_at<span class="pl-pds">"</span></span> <span class="pl-k">TIMESTAMP WITH TIME ZONE</span> <span class="pl-k">NOT NULL</span>,
  <span class="pl-s"><span class="pl-pds">"</span>updated_at<span class="pl-pds">"</span></span> <span class="pl-k">TIMESTAMP WITH TIME ZONE</span> <span class="pl-k">NOT NULL</span>,
  <span class="pl-k">PRIMARY KEY</span> (<span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>)
);
<span class="pl-k">CREATE</span> <span class="pl-k">TABLE</span> <span class="pl-en">IF</span> NOT EXISTS <span class="pl-s"><span class="pl-pds">"</span>tasks<span class="pl-pds">"</span></span> (
  <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span> <span class="pl-k">SERIAL</span>,
  <span class="pl-s"><span class="pl-pds">"</span>title<span class="pl-pds">"</span></span> <span class="pl-k">VARCHAR</span>(<span class="pl-c1">255</span>),
  <span class="pl-s"><span class="pl-pds">"</span>created_at<span class="pl-pds">"</span></span> <span class="pl-k">TIMESTAMP WITH TIME ZONE</span> <span class="pl-k">NOT NULL</span>,
  <span class="pl-s"><span class="pl-pds">"</span>updated_at<span class="pl-pds">"</span></span> <span class="pl-k">TIMESTAMP WITH TIME ZONE</span> <span class="pl-k">NOT NULL</span>,
  <span class="pl-s"><span class="pl-pds">"</span>user_id<span class="pl-pds">"</span></span> <span class="pl-k">INTEGER</span> <span class="pl-k">REFERENCES</span> <span class="pl-s"><span class="pl-pds">"</span>users<span class="pl-pds">"</span></span> (<span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>) <span class="pl-k">ON DELETE</span> <span class="pl-k">SET</span> <span class="pl-k">NULL</span> <span class="pl-k">ON</span> <span class="pl-k">UPDATE</span> CASCADE,
  <span class="pl-k">PRIMARY KEY</span> (<span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>)
);</pre>
  </div>
  <h2>单数与复数</h2>
  <p>乍看之下,在 Sequelize 中是否应使用名称的单数形式或复数形式可能会造成混淆. 本节旨在澄清这一点.</p>
  <p>回想一下 Sequelize 在后台使用了一个名为&nbsp;<a href="https://www.npmjs.com/package/inflection" rel="nofollow">inflection</a>&nbsp;的库,以便正确计算不规则的复数形式(例如&nbsp;<code>person -&gt; people</code>). 但是,如果你使用的是另一种语言,则可能需要直接定义名称的单数和复数形式. sequelize 允许你通过一些参数来执行此操作.</p>
  <h3>定义模型时</h3>
  <p>模型应以单词的单数形式定义. 例：</p>
  <div class="highlight highlight-source-js">
    <pre><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'foo'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>上面的模型名称是&nbsp;<code>foo</code>(单数),表名称是&nbsp;<code>foos</code>,因为 Sequelize 会自动获取表名称的复数形式.</p>
  <h3>在模型中定义参考键时</h3>
  <div class="highlight highlight-source-js">
<pre><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'foo'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">name</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">barId</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
    <span class="pl-c1">allowNull</span>: <span class="pl-c1">false</span><span class="pl-kos">,</span>
    <span class="pl-c1">references</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">model</span>: <span class="pl-s">"bars"</span><span class="pl-kos">,</span>
      <span class="pl-c1">key</span>: <span class="pl-s">"id"</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-c1">onDelete</span>: <span class="pl-s">"CASCADE"</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>在上面的示例中,我们手动定义了引用另一个模型的键. 这不是通常的做法,但是如果必须这样做,则应在此使用表名. 这是因为引用是根据引用的表名创建的. 在上面的示例中,使用了复数形式(<code>bars</code>),假设&nbsp;<code>bar</code>&nbsp;模型是使用默认设置创建的(使其基础表自动复数).</p>
  <h3>从预先加载中检索数据时</h3>
  <p>当你在查询中执行&nbsp;<code>include</code>&nbsp;时,包含的数据将根据以下规则添加到返回对象的额外字段中：</p>
  <ul>
    <li>当包含来自单个关联(<code>hasOne</code>&nbsp;或&nbsp;<code>belongsTo</code>)的内容时,字段名称将是模型名称的单数形式;</li>
    <li>当包含来自多个关联(<code>hasMany</code>&nbsp;或&nbsp;<code>belongsToMany</code>)的内容时,字段名称将是模型的复数形式.</li>
  </ul>
  <p>简而言之,在每种情况下,字段名称将采用最合乎逻辑的形式.</p>
  <p>示例:</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 假设 Foo.hasMany(Bar)</span>
<span class="pl-k">const</span> <span class="pl-s1">foo</span> <span class="pl-c1">=</span> <span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Bar</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// foo.bars 将是一个数组</span>
<span class="pl-c">// foo.bar 将不存在,因为它没有意义</span>

<span class="pl-c">// 假设 Foo.hasOne(Bar)</span>
<span class="pl-k">const</span> <span class="pl-s1">foo</span> <span class="pl-c1">=</span> <span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">include</span>: <span class="pl-v">Bar</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// foo.bar 将是一个对象(如果没有关联的模型,则可能为 null)</span>
<span class="pl-c">// foo.bars 将不存在,因为它没有意义</span>

<span class="pl-c">// 等等.</span></pre>
  </div>
  <h3>定义别名时覆盖单数和复数</h3>
  <p>在为关联定义别名时,你可以传递一个对象以指定单数和复数形式,而不仅仅是使用&nbsp;<code>{ as: 'myAlias' }</code>.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">User</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">as</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">singular</span>: <span class="pl-s">'l&iacute;der'</span><span class="pl-kos">,</span>
    <span class="pl-c1">plural</span>: <span class="pl-s">'l&iacute;deres'</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>如果你知道模型在关联中将始终使用相同的别名,则可以将单数和复数形式直接提供给模型本身：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">User</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'user'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c">/* ... */</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">name</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">singular</span>: <span class="pl-s">'l&iacute;der'</span><span class="pl-kos">,</span>
    <span class="pl-c1">plural</span>: <span class="pl-s">'l&iacute;deres'</span><span class="pl-kos">,</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">User</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>添加到用户实例的混入文件将使用正确的形式. 例如,Sequelize 将代替&nbsp;<code>project.addUser()</code>&nbsp;来提供&nbsp;<code>project.getL&iacute;der()</code>. 另外,Sequelize 将代替&nbsp;<code>project.setUsers()</code>&nbsp;来提供&nbsp;<code>project.setL&iacute;deres()</code>.</p>
  <p>注意：记得使用&nbsp;<code>as</code>&nbsp;来改变关联的名字也会改变外键的名字. 因此,建议也指定在这种情况下直接涉及的外键.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 错误示例</span>
<span class="pl-v">Invoice</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Subscription</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">as</span>: <span class="pl-s">'TheSubscription'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Subscription</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Invoice</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>上面的第一个调用将在&nbsp;<code>Invoice</code>&nbsp;上建立一个名为&nbsp;<code>theSubscriptionId</code>&nbsp;的外键. 但是,第二个调用也会在&nbsp;<code>Invoice</code>&nbsp;上建立外键(因为众所周知,&nbsp;<code>hasMany</code>&nbsp;调用会将外键放置在目标模型中)-但是,它将被命名为&nbsp;<code>subscriptionId</code>. 这样,你将同时具有&nbsp;<code>subscriptionId</code>&nbsp;和&nbsp;<code>theSubscriptionId</code>&nbsp;列.</p>
  <p>最好的方法是为外键选择一个名称,并将其显式放置在两个调用中. 例如,如果选择了&nbsp;<code>subscription_id</code>：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 修正示例</span>
<span class="pl-v">Invoice</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Subscription</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">as</span>: <span class="pl-s">'TheSubscription'</span><span class="pl-kos">,</span> <span class="pl-c1">foreignKey</span>: <span class="pl-s">'subscription_id'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Subscription</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Invoice</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">foreignKey</span>: <span class="pl-s">'subscription_id'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <pre><span class="pl-kos">&nbsp;</span></pre>
  <h1>Scopes - 作用域</h1>
  <p>作用域用于帮助你重用代码. 你可以定义常用查询,并指定诸如&nbsp;<code>where</code>,&nbsp;<code>include</code>,&nbsp;<code>limit</code>&nbsp;等参数.</p>
  <p>本指南涉及模型作用域. 你可能也对<a href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/advanced-association-concepts/association-scopes.md">关联作用域指南</a>感兴趣,它们相似但又不同.</p>
  <h2>定义</h2>
  <p>作用域在模型定义中定义,可以是查找器对象,也可以是返回查找器对象的函数 - 默认作用域除外,该作用域只能是一个对象：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">class</span> <span class="pl-v">Project</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c">// 属性</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">defaultScope</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">active</span>: <span class="pl-c1">true</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">scopes</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">deleted</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
        <span class="pl-c1">deleted</span>: <span class="pl-c1">true</span>
      <span class="pl-kos">}</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-c1">activeUsers</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">include</span>: <span class="pl-kos">[</span>
        <span class="pl-kos">{</span> <span class="pl-c1">model</span>: <span class="pl-v">User</span><span class="pl-kos">,</span> <span class="pl-c1">where</span>: <span class="pl-kos">{</span> <span class="pl-c1">active</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span> <span class="pl-kos">}</span>
      <span class="pl-kos">]</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-en">random</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-k">return</span> <span class="pl-kos">{</span>
        <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
          <span class="pl-c1">someNumber</span>: <span class="pl-v">Math</span><span class="pl-kos">.</span><span class="pl-en">random</span><span class="pl-kos">(</span><span class="pl-kos">)</span>
        <span class="pl-kos">}</span>
      <span class="pl-kos">}</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-en">accessLevel</span><span class="pl-kos">(</span><span class="pl-s1">value</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-k">return</span> <span class="pl-kos">{</span>
        <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
          <span class="pl-c1">accessLevel</span>: <span class="pl-kos">{</span>
            <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">gte</span><span class="pl-kos">]</span>: <span class="pl-s1">value</span>
          <span class="pl-kos">}</span>
        <span class="pl-kos">}</span>
      <span class="pl-kos">}</span>
    <span class="pl-kos">}</span>
    <span class="pl-s1">sequelize</span><span class="pl-kos">,</span>
    <span class="pl-c1">modelName</span>: <span class="pl-s">'project'</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>你也可以在定义模型后通过调用&nbsp;<a href="https://sequelize.org/master/class/lib/model.js~Model.html#static-method-addScope" rel="nofollow"><code>YourModel.addScope</code></a>&nbsp;添加作用域. 这对于具有包含的作用域特别有用,其中在定义另一个模型时可能未定义包含中的模型.</p>
  <p>始终应用默认作用域. 这意味着,使用上面的模型定义,<code>Project.findAll()</code>&nbsp;将创建以下查询：</p>
  <div class="highlight highlight-source-sql">
    <pre><span class="pl-k">SELECT</span> <span class="pl-k">*</span> <span class="pl-k">FROM</span> projects <span class="pl-k">WHERE</span> active <span class="pl-k">=</span> true</pre>
  </div>
  <p>可以通过调用&nbsp;<code>.unscoped()</code>,&nbsp;<code>.scope(null)</code>, 或调用另一个作用域来删除默认作用域：</p>
  <div class="highlight highlight-source-js">
    <pre><span class="pl-k">await</span> <span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">scope</span><span class="pl-kos">(</span><span class="pl-s">'deleted'</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 删除默认作用域</span></pre>
  </div>
  <div class="highlight highlight-source-sql">
    <pre><span class="pl-k">SELECT</span> <span class="pl-k">*</span> <span class="pl-k">FROM</span> projects <span class="pl-k">WHERE</span> deleted <span class="pl-k">=</span> true</pre>
  </div>
  <p>也可以在作用域定义中包括作用域模型. 这样可以避免重复&nbsp;<code>include</code>,&nbsp;<code>attributes</code>&nbsp;或&nbsp;<code>where</code>&nbsp;定义. 使用上面的示例,并在包含的用户模型上调用<code>active</code>&nbsp;作用域(而不是直接在该包含对象中指定条件)：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 上例中定义的 `activeUsers` 作用域也可以通过以下方式定义：</span>
<span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">addScope</span><span class="pl-kos">(</span><span class="pl-s">'activeUsers'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span> <span class="pl-c1">model</span>: <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">scope</span><span class="pl-kos">(</span><span class="pl-s">'active'</span><span class="pl-kos">)</span> <span class="pl-kos">}</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h2>使用</h2>
  <p>通过在模型定义上调用&nbsp;<code>.scope</code>,并传递一个或多个作用域的名称来应用作用域.<code>.scope</code>&nbsp;返回具有所有常规方法的功能齐全的模型实例：<code>.findAll</code>,&nbsp;<code>.update</code>,&nbsp;<code>.count</code>,&nbsp;<code>.destroy</code>&nbsp;等.你可以保存此模型实例并在以后重用：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">DeletedProjects</span> <span class="pl-c1">=</span> <span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">scope</span><span class="pl-kos">(</span><span class="pl-s">'deleted'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">await</span> <span class="pl-v">DeletedProjects</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 以上相当于:</span>
<span class="pl-k">await</span> <span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">deleted</span>: <span class="pl-c1">true</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>作用域适用于&nbsp;<code>.find</code>,&nbsp;<code>.findAll</code>,&nbsp;<code>.count</code>,&nbsp;<code>.update</code>,&nbsp;<code>.increment</code>&nbsp;和&nbsp;<code>.destroy</code>.</p>
  <p>作用域可以通过两种方式调用. 如果作用域不带任何参数,则可以正常调用它. 如果作用域接受参数,则传递一个对象：</p>
  <div class="highlight highlight-source-js">
    <pre><span class="pl-k">await</span> <span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">scope</span><span class="pl-kos">(</span><span class="pl-s">'random'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">method</span>: <span class="pl-kos">[</span><span class="pl-s">'accessLevel'</span><span class="pl-kos">,</span> <span class="pl-c1">19</span><span class="pl-kos">]</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>生成 SQL:</p>
  <div class="highlight highlight-source-sql">
    <pre><span class="pl-k">SELECT</span> <span class="pl-k">*</span> <span class="pl-k">FROM</span> projects <span class="pl-k">WHERE</span> someNumber <span class="pl-k">=</span> <span class="pl-c1">42</span> <span class="pl-k">AND</span> accessLevel <span class="pl-k">&gt;=</span> <span class="pl-c1">19</span></pre>
  </div>
  <h2>合并</h2>
  <p>通过将作用域数组传递给&nbsp;<code>.scope</code>&nbsp;或将作用域作为连续参数传递,可以同时应用多个作用域.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 这两个是等效的</span>
<span class="pl-k">await</span> <span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">scope</span><span class="pl-kos">(</span><span class="pl-s">'deleted'</span><span class="pl-kos">,</span> <span class="pl-s">'activeUsers'</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">await</span> <span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">scope</span><span class="pl-kos">(</span><span class="pl-kos">[</span><span class="pl-s">'deleted'</span><span class="pl-kos">,</span> <span class="pl-s">'activeUsers'</span><span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>生成 SQL:</p>
  <div class="highlight highlight-source-sql">
<pre><span class="pl-k">SELECT</span> <span class="pl-k">*</span> <span class="pl-k">FROM</span> projects
<span class="pl-k">INNER JOIN</span> users <span class="pl-k">ON</span> <span class="pl-c1">projects</span>.<span class="pl-c1">userId</span> <span class="pl-k">=</span> <span class="pl-c1">users</span>.<span class="pl-c1">id</span>
<span class="pl-k">WHERE</span> <span class="pl-c1">projects</span>.<span class="pl-c1">deleted</span> <span class="pl-k">=</span> true
<span class="pl-k">AND</span> <span class="pl-c1">users</span>.<span class="pl-c1">active</span> <span class="pl-k">=</span> true</pre>
  </div>
  <p>如果要在默认作用域之外应用另一个作用域,请将关键字&nbsp;<code>defaultScope</code>&nbsp;传递给<code>.scope</code>：</p>
  <div class="highlight highlight-source-js">
    <pre><span class="pl-k">await</span> <span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">scope</span><span class="pl-kos">(</span><span class="pl-s">'defaultScope'</span><span class="pl-kos">,</span> <span class="pl-s">'deleted'</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>生成 SQL:</p>
  <div class="highlight highlight-source-sql">
    <pre><span class="pl-k">SELECT</span> <span class="pl-k">*</span> <span class="pl-k">FROM</span> projects <span class="pl-k">WHERE</span> active <span class="pl-k">=</span> true <span class="pl-k">AND</span> deleted <span class="pl-k">=</span> true</pre>
  </div>
  <p>调用多个合并作用域时,后续合并作用域中的键将覆盖先前合并作用域中的键(类似于&nbsp;<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign" rel="nofollow">Object.assign</a>),除了将合并的&nbsp;<code>where</code>&nbsp;和&nbsp;<code>include</code>&nbsp;之外. 考虑两个作用域：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">YourMode</span><span class="pl-kos">.</span><span class="pl-en">addScope</span><span class="pl-kos">(</span><span class="pl-s">'scope1'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">firstName</span>: <span class="pl-s">'bob'</span><span class="pl-kos">,</span>
    <span class="pl-c1">age</span>: <span class="pl-kos">{</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">gt</span><span class="pl-kos">]</span>: <span class="pl-c1">20</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">limit</span>: <span class="pl-c1">2</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">YourMode</span><span class="pl-kos">.</span><span class="pl-en">addScope</span><span class="pl-kos">(</span><span class="pl-s">'scope2'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">age</span>: <span class="pl-kos">{</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">gt</span><span class="pl-kos">]</span>: <span class="pl-c1">30</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">limit</span>: <span class="pl-c1">10</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>使用&nbsp;<code>.scope('scope1', 'scope2')</code>&nbsp;将产生以下 WHERE 子句：</p>
  <div class="highlight highlight-source-sql">
    <pre><span class="pl-k">WHERE</span> firstName <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">'</span>bob<span class="pl-pds">'</span></span> <span class="pl-k">AND</span> age <span class="pl-k">&gt;</span> <span class="pl-c1">30</span> <span class="pl-k">LIMIT</span> <span class="pl-c1">10</span></pre>
  </div>
  <p>注意&nbsp;<code>limit</code>&nbsp;和&nbsp;<code>age</code>&nbsp;如何被&nbsp;<code>scope2</code>&nbsp;覆盖,而保留&nbsp;<code>firstName</code>.<code>limit</code>,&nbsp;<code>offset</code>,&nbsp;<code>order</code>,&nbsp;<code>paranoid</code>,&nbsp;<code>lock</code>&nbsp;和&nbsp;<code>raw</code>&nbsp;字段被覆盖,而&nbsp;<code>where</code>&nbsp;则被浅合并(这意味着相同的键将被覆盖).包含的合并策略将在后面讨论.</p>
  <p>注意,多个应用作用域的&nbsp;<code>attributes</code>&nbsp;键以始终保留&nbsp;<code>attributes.exclude</code>&nbsp;的方式合并. 这允许合并多个合并作用域,并且永远不会泄漏最终合并作用域中的敏感字段.</p>
  <p>当将查找对象直接传递给作用域模型上的&nbsp;<code>findAll</code>(和类似的查找器)时,适用相同的合并逻辑：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">scope</span><span class="pl-kos">(</span><span class="pl-s">'deleted'</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">firstName</span>: <span class="pl-s">'john'</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span></pre>
  </div>
  <p>生成的 where 子句：</p>
  <div class="highlight highlight-source-sql">
    <pre><span class="pl-k">WHERE</span> deleted <span class="pl-k">=</span> true <span class="pl-k">AND</span> firstName <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">'</span>john<span class="pl-pds">'</span></span></pre>
  </div>
  <p>在这里,&nbsp;<code>deleted</code>&nbsp;作用域与查找器合并. 如果我们将&nbsp;<code>where: { firstName: 'john', deleted: false }</code>&nbsp;传递给查找器,则&nbsp;<code>deleted</code>&nbsp;作用域将被覆盖.</p>
  <h3>合并 Include</h3>
  <p>Include 将基于所包含的模型进行递归合并. 这是 v5 上添加的功能非常强大的合并,并通过示例更好地理解.</p>
  <p>考虑模型&nbsp;<code>Foo</code>,&nbsp;<code>Bar</code>,&nbsp;<code>Baz</code>&nbsp;和&nbsp;<code>Qux</code>,它们具有一对多关联,如下所示：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">Foo</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'Foo'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Bar</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'Bar'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Baz</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'Baz'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Qux</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'Qux'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Bar</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">foreignKey</span>: <span class="pl-s">'fooId'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Bar</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Baz</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">foreignKey</span>: <span class="pl-s">'barId'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Baz</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Qux</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">foreignKey</span>: <span class="pl-s">'bazId'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>现在,考虑在 Foo 上定义的以下四个作用域:</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">addScope</span><span class="pl-kos">(</span><span class="pl-s">'includeEverything'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Bar</span><span class="pl-kos">,</span>
    <span class="pl-c1">include</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span>
      <span class="pl-c1">model</span>: <span class="pl-v">Baz</span><span class="pl-kos">,</span>
      <span class="pl-c1">include</span>: <span class="pl-v">Qux</span>
    <span class="pl-kos">}</span><span class="pl-kos">]</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">addScope</span><span class="pl-kos">(</span><span class="pl-s">'limitedBars'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Bar</span><span class="pl-kos">,</span>
    <span class="pl-c1">limit</span>: <span class="pl-c1">2</span>
  <span class="pl-kos">}</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">addScope</span><span class="pl-kos">(</span><span class="pl-s">'limitedBazs'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Bar</span><span class="pl-kos">,</span>
    <span class="pl-c1">include</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span>
      <span class="pl-c1">model</span>: <span class="pl-v">Baz</span><span class="pl-kos">,</span>
      <span class="pl-c1">limit</span>: <span class="pl-c1">2</span>
    <span class="pl-kos">}</span><span class="pl-kos">]</span>
  <span class="pl-kos">}</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">addScope</span><span class="pl-kos">(</span><span class="pl-s">'excludeBazName'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Bar</span><span class="pl-kos">,</span>
    <span class="pl-c1">include</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span>
      <span class="pl-c1">model</span>: <span class="pl-v">Baz</span><span class="pl-kos">,</span>
      <span class="pl-c1">attributes</span>: <span class="pl-kos">{</span>
        <span class="pl-c1">exclude</span>: <span class="pl-kos">[</span><span class="pl-s">'name'</span><span class="pl-kos">]</span>
      <span class="pl-kos">}</span>
    <span class="pl-kos">}</span><span class="pl-kos">]</span>
  <span class="pl-kos">}</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>这四个作用域可以很容易地进行深度合并,例如,通过调用&nbsp;<code>Foo.scope('includeEverything', 'limitedBars', 'limitedBazs', 'excludeBazName').findAll()</code>,这完全等同于调用以下代码：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">await</span> <span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">include</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">model</span>: <span class="pl-v">Bar</span><span class="pl-kos">,</span>
    <span class="pl-c1">limit</span>: <span class="pl-c1">2</span><span class="pl-kos">,</span>
    <span class="pl-c1">include</span>: <span class="pl-kos">[</span><span class="pl-kos">{</span>
      <span class="pl-c1">model</span>: <span class="pl-v">Baz</span><span class="pl-kos">,</span>
      <span class="pl-c1">limit</span>: <span class="pl-c1">2</span><span class="pl-kos">,</span>
      <span class="pl-c1">attributes</span>: <span class="pl-kos">{</span>
        <span class="pl-c1">exclude</span>: <span class="pl-kos">[</span><span class="pl-s">'name'</span><span class="pl-kos">]</span>
      <span class="pl-kos">}</span><span class="pl-kos">,</span>
      <span class="pl-c1">include</span>: <span class="pl-v">Qux</span>
    <span class="pl-kos">}</span><span class="pl-kos">]</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 以上等同于：</span>
<span class="pl-k">await</span> <span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">scope</span><span class="pl-kos">(</span><span class="pl-kos">[</span>
  <span class="pl-s">'includeEverything'</span><span class="pl-kos">,</span>
  <span class="pl-s">'limitedBars'</span><span class="pl-kos">,</span>
  <span class="pl-s">'limitedBazs'</span><span class="pl-kos">,</span>
  <span class="pl-s">'excludeBazName'</span>
<span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>观察如何将四个作用域合并为一个. 作用域的 include 根据所包含的模型进行合并. 如果一个作用域包含模型 A,另一个作用域包含模型 B,则合并结果将同时包含模型 A 和 B.另一方面,如果两个作用域都包含相同的模型 A,但具有不同的参数(例如嵌套包含或其他属性) ,这些将被递归合并,如上所示.</p>
  <p>上面说明的合并以完全相同的方式工作,而不管应用于作用域的顺序如何. 如果某个选项由两个不同的作用域设置,则顺序只会有所不同 - 上面的示例不是这种情况,因为每个作用域执行的操作都不相同.</p>
  <p>这种合并策略还可以与传递给&nbsp;<code>.findAll</code>,&nbsp;<code>.findOne</code>&nbsp;等的参数完全相同.</p>
  <pre><span class="pl-kos">&nbsp;</span></pre>
  <h1>Sub Queries - 子查询</h1>
  <p>考虑你有两个模型,即&nbsp;<code>Post</code>&nbsp;和&nbsp;<code>Reaction</code>,它们之间建立了一对多的关系,因此一个 post 有很多 reactions：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">Post</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'post'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
    <span class="pl-c1">content</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">const</span> <span class="pl-v">Reaction</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'reaction'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">timestamps</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Reaction</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Reaction</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Post</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p><em>注意: 我们已禁用时间戳,只是为了缩短下一个示例的查询时间.</em></p>
  <p>让我们用一些数据填充表格:</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">async</span> <span class="pl-k">function</span> <span class="pl-en">makePostWithReactions</span><span class="pl-kos">(</span><span class="pl-s1">content</span><span class="pl-kos">,</span> <span class="pl-s1">reactionTypes</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">const</span> <span class="pl-s1">post</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> content <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">await</span> <span class="pl-v">Reaction</span><span class="pl-kos">.</span><span class="pl-en">bulkCreate</span><span class="pl-kos">(</span>
        <span class="pl-s1">reactionTypes</span><span class="pl-kos">.</span><span class="pl-en">map</span><span class="pl-kos">(</span><span class="pl-s1">type</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">(</span><span class="pl-kos">{</span> type<span class="pl-kos">,</span> <span class="pl-c1">postId</span>: <span class="pl-s1">post</span><span class="pl-kos">.</span><span class="pl-c1">id</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
    <span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">return</span> <span class="pl-s1">post</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">await</span> <span class="pl-en">makePostWithReactions</span><span class="pl-kos">(</span><span class="pl-s">'Hello World'</span><span class="pl-kos">,</span> <span class="pl-kos">[</span>
    <span class="pl-s">'Like'</span><span class="pl-kos">,</span> <span class="pl-s">'Angry'</span><span class="pl-kos">,</span> <span class="pl-s">'Laugh'</span><span class="pl-kos">,</span> <span class="pl-s">'Like'</span><span class="pl-kos">,</span> <span class="pl-s">'Like'</span><span class="pl-kos">,</span> <span class="pl-s">'Angry'</span><span class="pl-kos">,</span> <span class="pl-s">'Sad'</span><span class="pl-kos">,</span> <span class="pl-s">'Like'</span>
<span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">await</span> <span class="pl-en">makePostWithReactions</span><span class="pl-kos">(</span><span class="pl-s">'My Second Post'</span><span class="pl-kos">,</span> <span class="pl-kos">[</span>
    <span class="pl-s">'Laugh'</span><span class="pl-kos">,</span> <span class="pl-s">'Laugh'</span><span class="pl-kos">,</span> <span class="pl-s">'Like'</span><span class="pl-kos">,</span> <span class="pl-s">'Laugh'</span>
<span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>现在,我们已经准备好子查询功能的示例.</p>
  <p>假设我们要通过 SQL 为每个帖子计算一个&nbsp;<code>laughReactionsCount&nbsp;</code>. 我们可以通过子查询来实现,例如：</p>
  <div class="highlight highlight-source-sql">
<pre><span class="pl-k">SELECT</span>
    <span class="pl-k">*</span>,
    (
        <span class="pl-k">SELECT</span> <span class="pl-c1">COUNT</span>(<span class="pl-k">*</span>)
        <span class="pl-k">FROM</span> reactions <span class="pl-k">AS</span> reaction
        <span class="pl-k">WHERE</span>
            <span class="pl-c1">reaction</span>.<span class="pl-c1">postId</span> <span class="pl-k">=</span> <span class="pl-c1">post</span>.<span class="pl-c1">id</span>
            <span class="pl-k">AND</span>
            <span class="pl-c1">reaction</span>.<span class="pl-c1">type</span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">"</span>Laugh<span class="pl-pds">"</span></span>
    ) <span class="pl-k">AS</span> laughReactionsCount
<span class="pl-k">FROM</span> posts <span class="pl-k">AS</span> post</pre>
  </div>
  <p>如果我们通过 Sequelize 运行上面的原始 SQL 查询,我们将得到:</p>
  <div class="highlight highlight-source-json">
<pre>[
  {
    <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>,
    <span class="pl-s"><span class="pl-pds">"</span>content<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>Hello World<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>laughReactionsCount<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>
  },
  {
    <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">2</span>,
    <span class="pl-s"><span class="pl-pds">"</span>content<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>My Second Post<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>laughReactionsCount<span class="pl-pds">"</span></span>: <span class="pl-c1">3</span>
  }
]</pre>
  </div>
  <p>那么,如何在 Sequelize 的帮助下实现这一目标,而不必手工编写整个原始查询呢？</p>
  <p>答案是: 通过将 finder 方法(例如,<code>findAll&nbsp;</code>)的&nbsp;<code>attributes&nbsp;</code>参数与&nbsp;<code>sequelize.literal</code>&nbsp;实用程序功能结合使用,可以直接在查询中插入任意内容,而不会自动转义.</p>
  <p>这意味着 Sequelize 将帮助你进行较大的主要查询,但是你仍然必须自己编写该子查询：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
    <span class="pl-c1">attributes</span>: <span class="pl-kos">{</span>
        <span class="pl-c1">include</span>: <span class="pl-kos">[</span>
            <span class="pl-kos">[</span>
                <span class="pl-c">// 注意下面的调用中的括号！</span>
                <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">literal</span><span class="pl-kos">(</span><span class="pl-s">`(</span>
<span class="pl-s">                    SELECT COUNT(*)</span>
<span class="pl-s">                    FROM reactions AS reaction</span>
<span class="pl-s">                    WHERE</span>
<span class="pl-s">                        reaction.postId = post.id</span>
<span class="pl-s">                        AND</span>
<span class="pl-s">                        reaction.type = "Laugh"</span>
<span class="pl-s">                )`</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
                <span class="pl-s">'laughReactionsCount'</span>
            <span class="pl-kos">]</span>
        <span class="pl-kos">]</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>*重要提示：由于&nbsp;<code>sequelize.literal</code>&nbsp;会插入任意内容而不进行转义,因此,它可能是(主要)安全漏洞的来源,因此值得特别注意. 它不应该在用户生成的内容上使用.*但是在这里,我们使用自己编写的带有固定字符串的&nbsp;<code>sequelize.literal</code>.因为我们知道我们在做什么.</p>
  <p>上面给出了以下输出:</p>
  <div class="highlight highlight-source-json">
<pre>[
  {
    <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>,
    <span class="pl-s"><span class="pl-pds">"</span>content<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>Hello World<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>laughReactionsCount<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>
  },
  {
    <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">2</span>,
    <span class="pl-s"><span class="pl-pds">"</span>content<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>My Second Post<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>laughReactionsCount<span class="pl-pds">"</span></span>: <span class="pl-c1">3</span>
  }
]</pre>
  </div>
  <p>成功!</p>
  <h2>使用子查询进行复杂排序</h2>
  <p>这个想法可用于实现复杂的排序,例如根据 post 具有的 laugh 数量来排序帖子：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Post</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
    <span class="pl-c1">attributes</span>: <span class="pl-kos">{</span>
        <span class="pl-c1">include</span>: <span class="pl-kos">[</span>
            <span class="pl-kos">[</span>
                <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">literal</span><span class="pl-kos">(</span><span class="pl-s">`(</span>
<span class="pl-s">                    SELECT COUNT(*)</span>
<span class="pl-s">                    FROM reactions AS reaction</span>
<span class="pl-s">                    WHERE</span>
<span class="pl-s">                        reaction.postId = post.id</span>
<span class="pl-s">                        AND</span>
<span class="pl-s">                        reaction.type = "Laugh"</span>
<span class="pl-s">                )`</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
                <span class="pl-s">'laughReactionsCount'</span>
            <span class="pl-kos">]</span>
        <span class="pl-kos">]</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-c1">order</span>: <span class="pl-kos">[</span>
        <span class="pl-kos">[</span><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">literal</span><span class="pl-kos">(</span><span class="pl-s">'laughReactionsCount'</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">'DESC'</span><span class="pl-kos">]</span>
    <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>结果:</p>
  <div class="highlight highlight-source-json">
<pre>[
  {
    <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">2</span>,
    <span class="pl-s"><span class="pl-pds">"</span>content<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>My Second Post<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>laughReactionsCount<span class="pl-pds">"</span></span>: <span class="pl-c1">3</span>
  },
  {
    <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>,
    <span class="pl-s"><span class="pl-pds">"</span>content<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>Hello World<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>laughReactionsCount<span class="pl-pds">"</span></span>: <span class="pl-c1">1</span>
  }
]</pre>
  </div>
  <h1>Other Data Types - 其他数据类型</h1>
  <p>除了<a href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/core-concepts/model-basics.md">模型基础</a>指南中提到的最常见的数据类型外,Sequelize 还提供了其他几种数据类型.</p>
  <h2>范围 (仅限 PostgreSQL)</h2>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">RANGE</span><span class="pl-kos">(</span><span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">)</span>    <span class="pl-c">// int4range</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">RANGE</span><span class="pl-kos">(</span><span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">BIGINT</span><span class="pl-kos">)</span>     <span class="pl-c">// int8range</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">RANGE</span><span class="pl-kos">(</span><span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">DATE</span><span class="pl-kos">)</span>       <span class="pl-c">// tstzrange</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">RANGE</span><span class="pl-kos">(</span><span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">DATEONLY</span><span class="pl-kos">)</span>   <span class="pl-c">// daterange</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">RANGE</span><span class="pl-kos">(</span><span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">DECIMAL</span><span class="pl-kos">)</span>    <span class="pl-c">// numrange</span></pre>
  </div>
  <p>由于范围类型对于它们绑定的 包含/排除 具有额外的信息,因此仅使用元组在 javascript 中表示它们并不是很容易.</p>
  <p>当提供范围值时,可以从以下 API 中进行选择：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 默认为包含下限,排除上限</span>
<span class="pl-k">const</span> <span class="pl-s1">range</span> <span class="pl-c1">=</span> <span class="pl-kos">[</span>
  <span class="pl-k">new</span> <span class="pl-v">Date</span><span class="pl-kos">(</span><span class="pl-v">Date</span><span class="pl-kos">.</span><span class="pl-en">UTC</span><span class="pl-kos">(</span><span class="pl-c1">2016</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
  <span class="pl-k">new</span> <span class="pl-v">Date</span><span class="pl-kos">(</span><span class="pl-v">Date</span><span class="pl-kos">.</span><span class="pl-en">UTC</span><span class="pl-kos">(</span><span class="pl-c1">2016</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">]</span><span class="pl-kos">;</span>
<span class="pl-c">// '["2016-01-01 00:00:00+00:00", "2016-02-01 00:00:00+00:00")'</span>

<span class="pl-c">// 控制包含</span>
<span class="pl-k">const</span> <span class="pl-s1">range</span> <span class="pl-c1">=</span> <span class="pl-kos">[</span>
  <span class="pl-kos">{</span> <span class="pl-c1">value</span>: <span class="pl-k">new</span> <span class="pl-v">Date</span><span class="pl-kos">(</span><span class="pl-v">Date</span><span class="pl-kos">.</span><span class="pl-en">UTC</span><span class="pl-kos">(</span><span class="pl-c1">2016</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-c1">inclusive</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-kos">{</span> <span class="pl-c1">value</span>: <span class="pl-k">new</span> <span class="pl-v">Date</span><span class="pl-kos">(</span><span class="pl-v">Date</span><span class="pl-kos">.</span><span class="pl-en">UTC</span><span class="pl-kos">(</span><span class="pl-c1">2016</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-c1">inclusive</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
<span class="pl-kos">]</span><span class="pl-kos">;</span>
<span class="pl-c">// '("2016-01-01 00:00:00+00:00", "2016-02-01 00:00:00+00:00"]'</span>

<span class="pl-c">// 复合形式</span>
<span class="pl-k">const</span> <span class="pl-s1">range</span> <span class="pl-c1">=</span> <span class="pl-kos">[</span>
  <span class="pl-kos">{</span> <span class="pl-c1">value</span>: <span class="pl-k">new</span> <span class="pl-v">Date</span><span class="pl-kos">(</span><span class="pl-v">Date</span><span class="pl-kos">.</span><span class="pl-en">UTC</span><span class="pl-kos">(</span><span class="pl-c1">2016</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-c1">inclusive</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-k">new</span> <span class="pl-v">Date</span><span class="pl-kos">(</span><span class="pl-v">Date</span><span class="pl-kos">.</span><span class="pl-en">UTC</span><span class="pl-kos">(</span><span class="pl-c1">2016</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
<span class="pl-kos">]</span><span class="pl-kos">;</span>
<span class="pl-c">// '("2016-01-01 00:00:00+00:00", "2016-02-01 00:00:00+00:00")'</span>

<span class="pl-k">const</span> <span class="pl-v">Timeline</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'Timeline'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">range</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">RANGE</span><span class="pl-kos">(</span><span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">DATE</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">await</span> <span class="pl-v">Timeline</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> range <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>然而,检索到的范围值始终以对象数组的形式出现. 例如,如果在 finder 查询后,存储的值是&nbsp;<code>("2016-01-01 00:00:00+00:00", "2016-02-01 00:00:00+00:00"]</code>&nbsp;你会得到：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-kos">[</span>
  <span class="pl-kos">{</span> <span class="pl-c1">value</span>: <span class="pl-v">Date</span><span class="pl-kos">,</span> <span class="pl-c1">inclusive</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-kos">{</span> <span class="pl-c1">value</span>: <span class="pl-v">Date</span><span class="pl-kos">,</span> <span class="pl-c1">inclusive</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span>
<span class="pl-kos">]</span></pre>
  </div>
  <p>使用范围类型更新实例后,你需要调用&nbsp;<code>reload()</code>&nbsp;或使用&nbsp;<code>returning: true</code>&nbsp;参数.</p>
  <h3>特别案例</h3>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 空范围:</span>
<span class="pl-v">Timeline</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">range</span>: <span class="pl-kos">[</span><span class="pl-kos">]</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// range = 'empty'</span>

<span class="pl-c">// 无界范围:</span>
<span class="pl-v">Timeline</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">range</span>: <span class="pl-kos">[</span><span class="pl-c1">null</span><span class="pl-kos">,</span> <span class="pl-c1">null</span><span class="pl-kos">]</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// range = '[,)'</span>
<span class="pl-c">// range = '[,"2016-01-01 00:00:00+00:00")'</span>
<span class="pl-v">Timeline</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">range</span>: <span class="pl-kos">[</span><span class="pl-c1">null</span><span class="pl-kos">,</span> <span class="pl-k">new</span> <span class="pl-v">Date</span><span class="pl-kos">(</span><span class="pl-v">Date</span><span class="pl-kos">.</span><span class="pl-en">UTC</span><span class="pl-kos">(</span><span class="pl-c1">2016</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">]</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 无限范围:</span>
<span class="pl-c">// range = '[-infinity,"2016-01-01 00:00:00+00:00")'</span>
<span class="pl-v">Timeline</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">range</span>: <span class="pl-kos">[</span><span class="pl-c1">-</span><span class="pl-v">Infinity</span><span class="pl-kos">,</span> <span class="pl-k">new</span> <span class="pl-v">Date</span><span class="pl-kos">(</span><span class="pl-v">Date</span><span class="pl-kos">.</span><span class="pl-en">UTC</span><span class="pl-kos">(</span><span class="pl-c1">2016</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">]</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h2>BLOB</h2>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">BLOB</span>                <span class="pl-c">// BLOB (PostgreSQL 的 bytea)</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">BLOB</span><span class="pl-kos">(</span><span class="pl-s">'tiny'</span><span class="pl-kos">)</span>        <span class="pl-c">// TINYBLOB (PostgreSQL 的 bytea)</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">BLOB</span><span class="pl-kos">(</span><span class="pl-s">'medium'</span><span class="pl-kos">)</span>      <span class="pl-c">// MEDIUMBLOB (PostgreSQL 的 bytea)</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">BLOB</span><span class="pl-kos">(</span><span class="pl-s">'long'</span><span class="pl-kos">)</span>        <span class="pl-c">// LONGBLOB (PostgreSQL 的 bytea)</span></pre>
  </div>
  <p>Blob 数据类型允许你将数据既作为字符串又作为缓冲区插入. 但是,当使用 Sequelize从 数据库中检索 Blob 时,将始终将其作为缓冲区检索.</p>
  <h2>ENUM</h2>
  <p>ENUM 是仅接受几个值(指定为列表)的数据类型.</p>
  <div class="highlight highlight-source-js">
    <pre><span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">ENUM</span><span class="pl-kos">(</span><span class="pl-s">'foo'</span><span class="pl-kos">,</span> <span class="pl-s">'bar'</span><span class="pl-kos">)</span> <span class="pl-c">// 允许值为'foo'和'bar'的ENUM</span></pre>
  </div>
  <p>也可以使用列定义的&nbsp;<code>values</code>&nbsp;字段指定 ENUM,如下所示：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'foo'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">states</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">ENUM</span><span class="pl-kos">,</span>
    <span class="pl-c1">values</span>: <span class="pl-kos">[</span><span class="pl-s">'active'</span><span class="pl-kos">,</span> <span class="pl-s">'pending'</span><span class="pl-kos">,</span> <span class="pl-s">'deleted'</span><span class="pl-kos">]</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h2>JSON (仅限 SQLite, MySQL, MariaDB 和 PostgreSQL)</h2>
  <p>仅 SQLite,MySQL,MariaDB 和 PostgreSQL 支持&nbsp;<code>DataTypes.JSON</code>&nbsp;数据类型. 但是,对 MSSQL 的支持最少(请参见下文).</p>
  <h3>PostgreSQL 的注意事项</h3>
  <p>PostgreSQL 中的 JSON 数据类型将值存储为纯文本,而不是二进制表示. 如果只想存储和检索 JSON 表示形式,则使用 JSON 将占用更少的磁盘空间,并需要更少的时间从其输入表示形式进行构建. 但是,如果要对 JSON 值执行任何操作,则应首选以下所述的 JSONB 数据类型.</p>
  <h3>JSONB (仅限 PostgreSQL)</h3>
  <p>PostgreSQL 还支持 JSONB 数据类型：&nbsp;<code>DataTypes.JSONB</code>. 可以通过三种不同的方式查询它：</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 嵌套对象</span>
<span class="pl-k">await</span> <span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">meta</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">video</span>: <span class="pl-kos">{</span>
        <span class="pl-c1">url</span>: <span class="pl-kos">{</span>
          <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">ne</span><span class="pl-kos">]</span>: <span class="pl-c1">null</span>
        <span class="pl-kos">}</span>
      <span class="pl-kos">}</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 嵌套键</span>
<span class="pl-k">await</span> <span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-s">"meta.audio.length"</span>: <span class="pl-kos">{</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">gt</span><span class="pl-kos">]</span>: <span class="pl-c1">20</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 包含限制</span>
<span class="pl-k">await</span> <span class="pl-v">Foo</span><span class="pl-kos">.</span><span class="pl-en">findOne</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">meta</span>: <span class="pl-kos">{</span>
      <span class="pl-kos">[</span><span class="pl-v">Op</span><span class="pl-kos">.</span><span class="pl-c1">contains</span><span class="pl-kos">]</span>: <span class="pl-kos">{</span>
        <span class="pl-c1">site</span>: <span class="pl-kos">{</span>
          <span class="pl-c1">url</span>: <span class="pl-s">'http://google.com'</span>
        <span class="pl-kos">}</span>
      <span class="pl-kos">}</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h3>MSSQL</h3>
  <p>MSSQL 没有 JSON 数据类型,但是自 SQL Server 2016 起,它确实通过某些函数提供了对以字符串形式存储的 JSON 的支持.使用这些函数,你将能够查询存储在字符串中的 JSON,但是所有返回的值将需要单独解析.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// ISJSON - 测试字符串是否包含有效的 JSON</span>
<span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">where</span><span class="pl-kos">(</span><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">fn</span><span class="pl-kos">(</span><span class="pl-s">'ISJSON'</span><span class="pl-kos">,</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">col</span><span class="pl-kos">(</span><span class="pl-s">'userDetails'</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span>

<span class="pl-c">// JSON_VALUE - 从 JSON 字符串中提取标量值</span>
<span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">attributes</span>: <span class="pl-kos">[</span><span class="pl-kos">[</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">fn</span><span class="pl-kos">(</span><span class="pl-s">'JSON_VALUE'</span><span class="pl-kos">,</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">col</span><span class="pl-kos">(</span><span class="pl-s">'userDetails'</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">'$.address.Line1'</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">'address line 1'</span><span class="pl-kos">]</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span>

<span class="pl-c">// JSON_VALUE - 从 JSON 字符串查询标量值</span>
<span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">where</span>: <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">where</span><span class="pl-kos">(</span><span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">fn</span><span class="pl-kos">(</span><span class="pl-s">'JSON_VALUE'</span><span class="pl-kos">,</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">col</span><span class="pl-kos">(</span><span class="pl-s">'userDetails'</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">'$.address.Line1'</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">'14, Foo Street'</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span>

<span class="pl-c">// JSON_QUERY - 提取对象或数组</span>
<span class="pl-k">await</span> <span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">findAll</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">attributes</span>: <span class="pl-kos">[</span><span class="pl-kos">[</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">fn</span><span class="pl-kos">(</span><span class="pl-s">'JSON_QUERY'</span><span class="pl-kos">,</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">col</span><span class="pl-kos">(</span><span class="pl-s">'userDetails'</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">'$.address'</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">'full address'</span><span class="pl-kos">]</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span></pre>
  </div>
  <h2>其他</h2>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">ARRAY</span><span class="pl-kos">(</span><span class="pl-c">/* DataTypes.SOMETHING */</span><span class="pl-kos">)</span>  <span class="pl-c">// 定义一个 DataTypes.SOMETHING 数组. 仅限 PostgreSQL.</span>

<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">CIDR</span>                        <span class="pl-c">// CIDR                  仅限 PostgreSQL</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INET</span>                        <span class="pl-c">// INET                  仅限 PostgreSQL</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">MACADDR</span>                     <span class="pl-c">// MACADDR               仅限 PostgreSQL</span>

<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">GEOMETRY</span>                    <span class="pl-c">// 空间列. 仅限 PostgreSQL (使用 PostGIS) 或 MySQL.</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">GEOMETRY</span><span class="pl-kos">(</span><span class="pl-s">'POINT'</span><span class="pl-kos">)</span>           <span class="pl-c">// 具有几何类型的空间列.仅限 PostgreSQL (使用 PostGIS) 或 MySQL.</span>
<span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-en">GEOMETRY</span><span class="pl-kos">(</span><span class="pl-s">'POINT'</span><span class="pl-kos">,</span> <span class="pl-c1">4326</span><span class="pl-kos">)</span>     <span class="pl-c">// 具有几何类型和 SRID 的空间列.仅限 PostgreSQL (使用 PostGIS) 或 MySQL.</span></pre>
  </div>
  <pre><span class="pl-kos">&nbsp;</span></pre>
  <h1>Constraints &amp; Circularities - 约束 &amp; 循环</h1>
  <p>在表之间添加约束意味着使用&nbsp;<code>sequelize.sync</code>&nbsp;时必须在数据库中以一定顺序创建表. 如果&nbsp;<code>Task</code>&nbsp;具有对&nbsp;<code>User</code>&nbsp;的引用,则必须先创建&nbsp;<code>User</code>&nbsp;表,然后才能创建&nbsp;<code>Task</code>&nbsp;表. 有时这可能会导致循环引用,而 Sequelize 无法找到同步的顺序. 想象一下文档和版本的情况. 一个文档可以有多个版本,为方便起见,文档引用了其当前版本.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> Sequelize<span class="pl-kos">,</span> Model<span class="pl-kos">,</span> DataTypes <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">"sequelize"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">class</span> <span class="pl-v">Document</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">Document</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
    <span class="pl-c1">author</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> sequelize<span class="pl-kos">,</span> <span class="pl-c1">modelName</span>: <span class="pl-s">'document'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">class</span> <span class="pl-v">Version</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">Version</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">timestamp</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">DATE</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> sequelize<span class="pl-kos">,</span> <span class="pl-c1">modelName</span>: <span class="pl-s">'version'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-v">Document</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Version</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 这会将 documentId 属性添加到 version 中</span>
<span class="pl-v">Document</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Version</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">as</span>: <span class="pl-s">'Current'</span><span class="pl-kos">,</span>
  <span class="pl-c1">foreignKey</span>: <span class="pl-s">'currentVersionId'</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 这会将 currentVersionId 属性添加到 document 中</span></pre>
  </div>
  <p>但是,不幸的是,上面的代码将导致以下错误:</p>
  <pre lang="text"><code>Cyclic dependency found. documents is dependent of itself. Dependency chain: documents -&gt; versions =&gt; documents
</code></pre>
  <p>为了减少这种情况,我们可以将&nbsp;<code>constraints: false</code>&nbsp;传递给关联之一:</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-v">Document</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Version</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Document</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Version</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">as</span>: <span class="pl-s">'Current'</span><span class="pl-kos">,</span>
  <span class="pl-c1">foreignKey</span>: <span class="pl-s">'currentVersionId'</span><span class="pl-kos">,</span>
  <span class="pl-c1">constraints</span>: <span class="pl-c1">false</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>这将使我们能够正确同步表:</p>
  <div class="highlight highlight-source-sql">
<pre><span class="pl-k">CREATE</span> <span class="pl-k">TABLE</span> <span class="pl-en">IF</span> NOT EXISTS <span class="pl-s"><span class="pl-pds">"</span>documents<span class="pl-pds">"</span></span> (
  <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span> <span class="pl-k">SERIAL</span>,
  <span class="pl-s"><span class="pl-pds">"</span>author<span class="pl-pds">"</span></span> <span class="pl-k">VARCHAR</span>(<span class="pl-c1">255</span>),
  <span class="pl-s"><span class="pl-pds">"</span>createdAt<span class="pl-pds">"</span></span> <span class="pl-k">TIMESTAMP WITH TIME ZONE</span> <span class="pl-k">NOT NULL</span>,
  <span class="pl-s"><span class="pl-pds">"</span>updatedAt<span class="pl-pds">"</span></span> <span class="pl-k">TIMESTAMP WITH TIME ZONE</span> <span class="pl-k">NOT NULL</span>,
  <span class="pl-s"><span class="pl-pds">"</span>currentVersionId<span class="pl-pds">"</span></span> <span class="pl-k">INTEGER</span>,
  <span class="pl-k">PRIMARY KEY</span> (<span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>)
);

<span class="pl-k">CREATE</span> <span class="pl-k">TABLE</span> <span class="pl-en">IF</span> NOT EXISTS <span class="pl-s"><span class="pl-pds">"</span>versions<span class="pl-pds">"</span></span> (
  <span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span> <span class="pl-k">SERIAL</span>,
  <span class="pl-s"><span class="pl-pds">"</span>timestamp<span class="pl-pds">"</span></span> <span class="pl-k">TIMESTAMP WITH TIME ZONE</span>,
  <span class="pl-s"><span class="pl-pds">"</span>createdAt<span class="pl-pds">"</span></span> <span class="pl-k">TIMESTAMP WITH TIME ZONE</span> <span class="pl-k">NOT NULL</span>,
  <span class="pl-s"><span class="pl-pds">"</span>updatedAt<span class="pl-pds">"</span></span> <span class="pl-k">TIMESTAMP WITH TIME ZONE</span> <span class="pl-k">NOT NULL</span>,
  <span class="pl-s"><span class="pl-pds">"</span>documentId<span class="pl-pds">"</span></span> <span class="pl-k">INTEGER</span> <span class="pl-k">REFERENCES</span> <span class="pl-s"><span class="pl-pds">"</span>documents<span class="pl-pds">"</span></span> (<span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>) <span class="pl-k">ON DELETE</span>
  <span class="pl-k">SET</span>
    <span class="pl-k">NULL</span> <span class="pl-k">ON</span> <span class="pl-k">UPDATE</span> CASCADE,
    <span class="pl-k">PRIMARY KEY</span> (<span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>)
);</pre>
  </div>
  <h2>不受限制地强制执行外键引用</h2>
  <p>有时,你可能希望引用另一个表,而不添加任何约束或关联. 在这种情况下,你可以将引用属性手动添加到架构定义中,并标记它们之间的关系.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">class</span> <span class="pl-v">Trainer</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">Trainer</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">firstName</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">lastName</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> sequelize<span class="pl-kos">,</span> <span class="pl-c1">modelName</span>: <span class="pl-s">'trainer'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 在我们调用 Trainer.hasMany(series) 之后,</span>
<span class="pl-c">// Series 将会有一个 trainerId = Trainer.id 外参考键</span>
<span class="pl-k">class</span> <span class="pl-v">Series</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">Series</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">title</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">subTitle</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">description</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">TEXT</span><span class="pl-kos">,</span>
  <span class="pl-c">// 设置与 `Trainer` 的外键关系(hasMany)</span>
  <span class="pl-c1">trainerId</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
    <span class="pl-c1">references</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">model</span>: <span class="pl-v">Trainer</span><span class="pl-kos">,</span>
      <span class="pl-c1">key</span>: <span class="pl-s">'id'</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> sequelize<span class="pl-kos">,</span> <span class="pl-c1">modelName</span>: <span class="pl-s">'series'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 在我们调用 Series.hasOne(Video) 之后,</span>
<span class="pl-c">// Video 将具有 seriesId = Series.id 外参考键</span>
<span class="pl-k">class</span> <span class="pl-v">Video</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">Video</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">title</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
  <span class="pl-c1">sequence</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
  <span class="pl-c1">description</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">TEXT</span><span class="pl-kos">,</span>
  <span class="pl-c">// 设置与 `Series` 的关系(hasOne)</span>
  <span class="pl-c1">seriesId</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
    <span class="pl-c1">references</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">model</span>: <span class="pl-v">Series</span><span class="pl-kos">,</span> <span class="pl-c">// 可以是代表表名的字符串,也可以是 Sequelize 模型</span>
      <span class="pl-c1">key</span>: <span class="pl-s">'id'</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> sequelize<span class="pl-kos">,</span> <span class="pl-c1">modelName</span>: <span class="pl-s">'video'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-v">Series</span><span class="pl-kos">.</span><span class="pl-en">hasOne</span><span class="pl-kos">(</span><span class="pl-v">Video</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Trainer</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Series</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <pre><span class="pl-kos">&nbsp;</span></pre>
  <h1>Extending Data Types - 扩展数据类型</h1>
  <p>你尝试实现的类型很可能已经包含在<a href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/core-concepts/model-basics.md">数据类型</a>中. 如果不包括新的数据类型,本手册将说明如何自己编写它.</p>
  <p>Sequelize 不会在数据库中创建新的数据类型. 本教程说明了如何使 Sequelize 识别新数据类型,并假定这些新数据类型已在数据库中创建.</p>
  <p>要扩展 Sequelize 数据类型,请在创建 Sequelize 实例之前进行.</p>
  <h2>示例</h2>
  <p>在此示例中,我们将创建一个名为&nbsp;<code>SOMETYPE</code>&nbsp;的类型,该类型将复制内置数据类型&nbsp;<code>DataTypes.INTEGER(11).ZEROFILL.UNSIGNED</code>.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-kos">{</span> Sequelize<span class="pl-kos">,</span> DataTypes<span class="pl-kos">,</span> Utils <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'Sequelize'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-en">createTheNewDataType</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-s">'sqlite::memory:'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">function</span> <span class="pl-en">createTheNewDataType</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>

  <span class="pl-k">class</span> <span class="pl-c1">SOMETYPE</span> <span class="pl-k">extends</span> <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">ABSTRACT</span> <span class="pl-kos">{</span>
    <span class="pl-c">// 强制性的: 在数据库中完整定义新类型</span>
    <span class="pl-en">toSql</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-k">return</span> <span class="pl-s">'INTEGER(11) UNSIGNED ZEROFILL'</span>
    <span class="pl-kos">}</span>

    <span class="pl-c">// 可选的: 验证器功能</span>
    <span class="pl-en">validate</span><span class="pl-kos">(</span><span class="pl-s1">value</span><span class="pl-kos">,</span> <span class="pl-s1">options</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-k">return</span> <span class="pl-kos">(</span><span class="pl-k">typeof</span> <span class="pl-s1">value</span> <span class="pl-c1">===</span> <span class="pl-s">'number'</span><span class="pl-kos">)</span> <span class="pl-c1">&amp;&amp;</span> <span class="pl-kos">(</span>!<span class="pl-v">Number</span><span class="pl-kos">.</span><span class="pl-en">isNaN</span><span class="pl-kos">(</span><span class="pl-s1">value</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>

    <span class="pl-c">// 可选的: sanitizer</span>
    <span class="pl-en">_sanitize</span><span class="pl-kos">(</span><span class="pl-s1">value</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-c">// 强制所有数字为正</span>
      <span class="pl-k">return</span> <span class="pl-s1">value</span> <span class="pl-c1">&lt;</span> <span class="pl-c1">0</span> ? <span class="pl-c1">0</span> : <span class="pl-v">Math</span><span class="pl-kos">.</span><span class="pl-en">round</span><span class="pl-kos">(</span><span class="pl-s1">value</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>

    <span class="pl-c">// 可选的: 发送到数据库之前的值字符串化</span>
    <span class="pl-en">_stringify</span><span class="pl-kos">(</span><span class="pl-s1">value</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-k">return</span> <span class="pl-s1">value</span><span class="pl-kos">.</span><span class="pl-en">toString</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>

    <span class="pl-c">// 可选的: 解析器,用于从数据库接收的值</span>
    <span class="pl-k">static</span> <span class="pl-en">parse</span><span class="pl-kos">(</span><span class="pl-s1">value</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-k">return</span> <span class="pl-v">Number</span><span class="pl-kos">.</span><span class="pl-en">parseInt</span><span class="pl-kos">(</span><span class="pl-s1">value</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>

  <span class="pl-c">// 强制性的: 设置类型键</span>
  <span class="pl-c1">SOMETYPE</span><span class="pl-kos">.</span><span class="pl-c1">prototype</span><span class="pl-kos">.</span><span class="pl-c1">key</span> <span class="pl-c1">=</span> <span class="pl-c1">SOMETYPE</span><span class="pl-kos">.</span><span class="pl-c1">key</span> <span class="pl-c1">=</span> <span class="pl-s">'SOMETYPE'</span><span class="pl-kos">;</span>

  <span class="pl-c">// 强制性的: 将新类型添加到数据类型. 将其包装在 `Utils.classToInvokable` 上,</span>
  <span class="pl-c">// 以能够直接使用此数据类型,而不必调用 `new`.</span>
  <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">SOMETYPE</span> <span class="pl-c1">=</span> <span class="pl-v">Utils</span><span class="pl-kos">.</span><span class="pl-en">classToInvokable</span><span class="pl-kos">(</span><span class="pl-c1">SOMETYPE</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

  <span class="pl-c">// 可选的: 禁用字符串化后的转义. 这样做需要你自担风险,因为这为 SQL 注入提供了机会.</span>
  <span class="pl-c">// DataTypes.SOMETYPE.escape = false;</span>

<span class="pl-kos">}</span></pre>
  </div>
  <p>创建此新数据类型后,你需要在每个数据库方言中映射此数据类型并进行一些调整.</p>
  <h2>PostgreSQL</h2>
  <p>假设新数据类型的名称在 postgres 数据库中为&nbsp;<code>pg_new_type</code>. 该名称必须映射到&nbsp;<code>DataTypes.SOMETYPE</code>. 此外,还需要创建特定于 Postgres 的子数据类型.</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">function</span> <span class="pl-en">createTheNewDataType</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-c">// [...]</span>

  <span class="pl-k">const</span> <span class="pl-v">PgTypes</span> <span class="pl-c1">=</span> <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">postgres</span><span class="pl-kos">;</span>

  <span class="pl-c">// 强制性的: 映射 postgres 数据类型名称</span>
  <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">SOMETYPE</span><span class="pl-kos">.</span><span class="pl-c1">types</span><span class="pl-kos">.</span><span class="pl-c1">postgres</span> <span class="pl-c1">=</span> <span class="pl-kos">[</span><span class="pl-s">'pg_new_type'</span><span class="pl-kos">]</span><span class="pl-kos">;</span>

  <span class="pl-c">// 强制性的: 使用自己的解析方法创建特定于 postgres 的子数据类型.</span>
  <span class="pl-c">// 解析器将动态映射到 pg_new_type 的 OID.</span>
  <span class="pl-v">PgTypes</span><span class="pl-kos">.</span><span class="pl-en">SOMETYPE</span> <span class="pl-c1">=</span> <span class="pl-k">function</span> <span class="pl-c1">SOMETYPE</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">if</span> <span class="pl-kos">(</span>!<span class="pl-kos">(</span><span class="pl-smi">this</span> <span class="pl-k">instanceof</span> <span class="pl-v">PgTypes</span><span class="pl-kos">.</span><span class="pl-c1">SOMETYPE</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-k">return</span> <span class="pl-k">new</span> <span class="pl-v">PgTypes</span><span class="pl-kos">.</span><span class="pl-c1">SOMETYPE</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
    <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">SOMETYPE</span><span class="pl-kos">.</span><span class="pl-en">apply</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-smi">arguments</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
  <span class="pl-k">const</span> <span class="pl-s1">util</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'util'</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// Node 包内置</span>
  <span class="pl-s1">util</span><span class="pl-kos">.</span><span class="pl-en">inherits</span><span class="pl-kos">(</span><span class="pl-v">PgTypes</span><span class="pl-kos">.</span><span class="pl-c1">SOMETYPE</span><span class="pl-kos">,</span> <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">SOMETYPE</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

  <span class="pl-c">// 强制性的: 创建,覆盖或重新分配特定于 Postgres 的解析器</span>
  <span class="pl-c">// PgTypes.SOMETYPE.parse = value =&gt; value;</span>
  <span class="pl-v">PgTypes</span><span class="pl-kos">.</span><span class="pl-c1">SOMETYPE</span><span class="pl-kos">.</span><span class="pl-c1">parse</span> <span class="pl-c1">=</span> <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">SOMETYPE</span><span class="pl-kos">.</span><span class="pl-c1">parse</span> <span class="pl-c1">||</span> <span class="pl-s1">x</span> <span class="pl-c1">=&gt;</span> <span class="pl-s1">x</span><span class="pl-kos">;</span>

  <span class="pl-c">// 可选的: 添加或覆盖特定于Postgres数据类型的方法,</span>
  <span class="pl-c">// 例如 toSql, escape, validate, _stringify, _sanitize...</span>

<span class="pl-kos">}</span></pre>
  </div>
  <h3>范围</h3>
  <p>在<a href="https://www.postgresql.org/docs/current/static/rangetypes.html#RANGETYPES-DEFINING" rel="nofollow">postgres中定义</a>了新的范围类型后,将其添加到 Sequelize 变得很简单.</p>
  <p>在此示例中,postgres 范围类型的名称为&nbsp;<code>SOMETYPE_range</code>,基础 postgres 数据类型的名称为&nbsp;<code>pg_new_type</code>.&nbsp;<code>subtypes</code>&nbsp;和&nbsp;<code>castTypes</code>&nbsp;的键是 Sequelize 数据类型&nbsp;<code>DataTypes.SOMETYPE.key</code>&nbsp;的键(小写).</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">function</span> <span class="pl-en">createTheNewDataType</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-c">// [...]</span>

  <span class="pl-c">// 添加 postgresql 范围,SOMETYPE 来自 DataType.SOMETYPE.key(小写)</span>
  <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">RANGE</span><span class="pl-kos">.</span><span class="pl-c1">types</span><span class="pl-kos">.</span><span class="pl-c1">postgres</span><span class="pl-kos">.</span><span class="pl-c1">subtypes</span><span class="pl-kos">.</span><span class="pl-c1">SOMETYPE</span> <span class="pl-c1">=</span> <span class="pl-s">'SOMETYPE_range'</span><span class="pl-kos">;</span>
  <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">RANGE</span><span class="pl-kos">.</span><span class="pl-c1">types</span><span class="pl-kos">.</span><span class="pl-c1">postgres</span><span class="pl-kos">.</span><span class="pl-c1">castTypes</span><span class="pl-kos">.</span><span class="pl-c1">SOMETYPE</span> <span class="pl-c1">=</span> <span class="pl-s">'pg_new_type'</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre>
  </div>
  <p>新范围可在模型定义中用作&nbsp;<code>DataTypes.RANGE(DataTypes.SOMETYPE)</code>&nbsp;或&nbsp;<code>DataTypes.RANGE(DataTypes.SOMETYPE)</code>.</p>
  <h1>Indexes - 索引</h1>
  <p>Sequelize 支持在模型定义上添加索引,该索引将在&nbsp;<a href="https://sequelize.org/master/class/lib/sequelize.js~Sequelize.html#instance-method-sync" rel="nofollow"><code>sequelize.sync()</code></a>&nbsp;上创建</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-v">User</span> <span class="pl-c1">=</span> <span class="pl-s1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-s">'User'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c">/* 属性 */</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">indexes</span>: <span class="pl-kos">[</span>
    <span class="pl-c">// 在 email 上创建唯一索引</span>
    <span class="pl-kos">{</span>
      <span class="pl-c1">unique</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
      <span class="pl-c1">fields</span>: <span class="pl-kos">[</span><span class="pl-s">'email'</span><span class="pl-kos">]</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">// 使用 jsonb_path_ops 运算符在 data 上创建 gin 索引</span>
    <span class="pl-kos">{</span>
      <span class="pl-c1">fields</span>: <span class="pl-kos">[</span><span class="pl-s">'data'</span><span class="pl-kos">]</span><span class="pl-kos">,</span>
      <span class="pl-c1">using</span>: <span class="pl-s">'gin'</span><span class="pl-kos">,</span>
      <span class="pl-c1">operator</span>: <span class="pl-s">'jsonb_path_ops'</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">// 默认情况下,索引名称将为 [table]_[fields]</span>
    <span class="pl-c">// 创建多列部分索引</span>
    <span class="pl-kos">{</span>
      <span class="pl-c1">name</span>: <span class="pl-s">'public_by_author'</span><span class="pl-kos">,</span>
      <span class="pl-c1">fields</span>: <span class="pl-kos">[</span><span class="pl-s">'author'</span><span class="pl-kos">,</span> <span class="pl-s">'status'</span><span class="pl-kos">]</span><span class="pl-kos">,</span>
      <span class="pl-c1">where</span>: <span class="pl-kos">{</span>
        <span class="pl-c1">status</span>: <span class="pl-s">'public'</span>
      <span class="pl-kos">}</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">// 具有 order 字段的 BTREE 索引</span>
    <span class="pl-kos">{</span>
      <span class="pl-c1">name</span>: <span class="pl-s">'title_index'</span><span class="pl-kos">,</span>
      <span class="pl-c1">using</span>: <span class="pl-s">'BTREE'</span><span class="pl-kos">,</span>
      <span class="pl-c1">fields</span>: <span class="pl-kos">[</span>
        <span class="pl-s">'author'</span><span class="pl-kos">,</span>
        <span class="pl-kos">{</span>
          <span class="pl-c1">attribute</span>: <span class="pl-s">'title'</span><span class="pl-kos">,</span>
          <span class="pl-c1">collate</span>: <span class="pl-s">'en_US'</span><span class="pl-kos">,</span>
          <span class="pl-c1">order</span>: <span class="pl-s">'DESC'</span><span class="pl-kos">,</span>
          <span class="pl-c1">length</span>: <span class="pl-c1">5</span>
        <span class="pl-kos">}</span>
      <span class="pl-kos">]</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <div class="application-main " data-commit-hovercards-enabled="" data-discussion-hovercards-enabled="" data-issue-and-pr-hovercards-enabled="">
    <div class=""><main>
      <div class="container-xl clearfix new-discussion-timeline px-3 px-md-4 px-lg-5">
        <div class="repository-content ">
          <div class="Box mt-3 position-relative
      ">
            <div id="readme" class="Box-body readme blob js-code-block-container p-5 p-xl-6 gist-border-0">
              <article class="markdown-body entry-content container-lg">
                <h1>Optimistic Locking - 乐观锁定</h1>
                <p>Sequelize 内置支持通过模型实例版本计数进行乐观锁定.</p>
                <p>乐观锁定默认情况下处于禁用状态,可以通过在特定模型定义或全局模型配置中将&nbsp;<code>version</code>&nbsp;属性设置为 true 来启用. 有关更多详细信息,请参见<a href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/core-concepts/model-basics.md">模型基础</a>.</p>
                <p>乐观锁定允许并发访问模型记录以进行编辑,并防止冲突覆盖数据. 它通过检查自从读取以来另一个进程是否对记录进行了更改,并在检测到冲突时抛出 OptimisticLockError 来执行此操作.</p>
              </article>
            </div>
          </div>
        </div>
      </div>
    </main></div>
  </div>
</div>
<div class="position-relative d-flex flex-row-reverse flex-lg-row flex-wrap flex-lg-nowrap flex-justify-center flex-lg-justify-between flex-sm-items-center pt-6 pb-2 mt-6 f6 text-gray border-top border-gray-light ">
  <h1>Read Replication - 读取复制</h1>
  <p>Sequelize 支持&nbsp;<a href="https://en.wikipedia.org/wiki/Replication_%28computing%29#Database_replication" rel="nofollow">读取复制</a>, 即,当你要执行 SELECT 查询时,可以连接多个服务器. 当你执行读取复制时,你可以指定一台或多台服务器充当读取副本,并指定一台服务器充当写入主机,该主机处理所有写入和更新并将它们传播到副本(请注意,实际复制过程&nbsp;<em>不是</em>&nbsp;由 Sequelize 处理,而应由数据库后端设置).</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-s">'database'</span><span class="pl-kos">,</span> <span class="pl-c1">null</span><span class="pl-kos">,</span> <span class="pl-c1">null</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">dialect</span>: <span class="pl-s">'mysql'</span><span class="pl-kos">,</span>
  <span class="pl-c1">port</span>: <span class="pl-c1">3306</span>
  <span class="pl-s1">replication</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">read</span>: <span class="pl-kos">[</span>
      <span class="pl-kos">{</span> <span class="pl-c1">host</span>: <span class="pl-s">'8.8.8.8'</span><span class="pl-kos">,</span> <span class="pl-c1">username</span>: <span class="pl-s">'read-1-username'</span><span class="pl-kos">,</span> <span class="pl-c1">password</span>: <span class="pl-s1">process</span><span class="pl-kos">.</span><span class="pl-c1">env</span><span class="pl-kos">.</span><span class="pl-c1">READ_DB_1_PW</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
      <span class="pl-kos">{</span> <span class="pl-c1">host</span>: <span class="pl-s">'9.9.9.9'</span><span class="pl-kos">,</span> <span class="pl-c1">username</span>: <span class="pl-s">'read-2-username'</span><span class="pl-kos">,</span> <span class="pl-c1">password</span>: <span class="pl-s1">process</span><span class="pl-kos">.</span><span class="pl-c1">env</span><span class="pl-kos">.</span><span class="pl-c1">READ_DB_2_PW</span> <span class="pl-kos">}</span>
    <span class="pl-kos">]</span><span class="pl-kos">,</span>
    <span class="pl-c1">write</span>: <span class="pl-kos">{</span> <span class="pl-c1">host</span>: <span class="pl-s">'1.1.1.1'</span><span class="pl-kos">,</span> <span class="pl-c1">username</span>: <span class="pl-s">'write-username'</span><span class="pl-kos">,</span> <span class="pl-c1">password</span>: <span class="pl-s1">process</span><span class="pl-kos">.</span><span class="pl-c1">env</span><span class="pl-kos">.</span><span class="pl-c1">WRITE_DB_PW</span> <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">pool</span>: <span class="pl-kos">{</span> <span class="pl-c">// 如果要覆盖用于 读/写 池的参数,可以在此处执行</span>
    <span class="pl-c1">max</span>: <span class="pl-c1">20</span><span class="pl-kos">,</span>
    <span class="pl-c1">idle</span>: <span class="pl-c1">30000</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span></pre>
  </div>
  <p>如果你有适用于所有副本的常规设置,则无需为每个实例提供它们. 在上面的代码中,数据库名称和端口将传播到所有副本. 如果将用户名和密码留给任何副本,则同样会生效. 每个副本具有以下参数：<code>host</code>,&nbsp;<code>port</code>,&nbsp;<code>username</code>,&nbsp;<code>password</code>,&nbsp;<code>database</code>.</p>
  <p>Sequelize 使用池来管理与副本的连接. 在内部,Sequelize 将维护使用&nbsp;<code>pool</code>&nbsp;配置创建的两个池.</p>
  <p>如果要修改这些设置,可以在实例化 Sequelize 时将 pool 作为参数传递,如上所示.</p>
  <p>每个&nbsp;<code>write</code>&nbsp;或&nbsp;<code>useMaster: true</code>&nbsp;查询都将使用写入池. 对于&nbsp;<code>SELECT</code>,将使用读取池. 使用基本的循环调度来切换只读副本.</p>
</div>
<p>&nbsp;</p>
<h1>Connection Pool - 连接池</h1>
<p>如果要从单个进程连接到数据库,则应仅创建一个 Sequelize 实例. Sequelize 将在初始化时建立连接池. 可以通过构造函数的&nbsp;<code>options</code>&nbsp;参数(使用&nbsp;<code>options.pool</code>)来配置此连接池,如以下示例所示：</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">sequelize</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Sequelize</span><span class="pl-kos">(</span><span class="pl-c">/* ... */</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c">// ...</span>
  <span class="pl-c1">pool</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">max</span>: <span class="pl-c1">5</span><span class="pl-kos">,</span>
    <span class="pl-c1">min</span>: <span class="pl-c1">0</span><span class="pl-kos">,</span>
    <span class="pl-c1">acquire</span>: <span class="pl-c1">30000</span><span class="pl-kos">,</span>
    <span class="pl-c1">idle</span>: <span class="pl-c1">10000</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
</div>
<p>在&nbsp;<a href="https://sequelize.org/master/class/lib/sequelize.js~Sequelize.html#instance-constructor-constructor" rel="nofollow">Sequelize 构造函数的 API 参考</a>中了解更多信息. 如果要从多个进程连接到数据库,则必须为每个进程创建一个实例,但是每个实例的最大连接池大小应达到最大总大小. 例如,如果你希望最大连接池大小为90,并且有三个进程,则每个进程的 Sequelize 实例的最大连接池大小应为30.</p>
<div class="highlight highlight-source-js">
  <pre><br /><br /></pre>
  <h1>Working with Legacy Tables - 使用遗留表</h1>
  <p>虽然 Sequelize 自认为可以开箱即用, 但是如果你要处理遗留表并向前验证应用程序,仅需要通过定义(否则生成)表和字段名称即可.</p>
  <h2><a id="user-content-表" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/legacy.md#%E8%A1%A8" aria-hidden="true"></a>表</h2>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">class</span> <span class="pl-v">User</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c">// ...</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">modelName</span>: <span class="pl-s">'user'</span><span class="pl-kos">,</span>
  <span class="pl-c1">tableName</span>: <span class="pl-s">'users'</span><span class="pl-kos">,</span>
  sequelize<span class="pl-kos">,</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h2><a id="user-content-字段" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/legacy.md#%E5%AD%97%E6%AE%B5" aria-hidden="true"></a>字段</h2>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">class</span> <span class="pl-v">MyModel</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">MyModel</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">userId</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
    <span class="pl-c1">field</span>: <span class="pl-s">'user_id'</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> sequelize <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <h2><a id="user-content-主键" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/legacy.md#%E4%B8%BB%E9%94%AE" aria-hidden="true"></a>主键</h2>
  <p>默认情况下,Sequelize 会假设你的表具有&nbsp;<code>id</code>&nbsp;主键属性.</p>
  <p>定义自己的主键:</p>
  <div class="highlight highlight-source-js">
<pre><span class="pl-k">class</span> <span class="pl-v">Collection</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">Collection</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">uid</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
    <span class="pl-c1">primaryKey</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
    <span class="pl-c1">autoIncrement</span>: <span class="pl-c1">true</span> <span class="pl-c">// 自动转换为 PostgreSQL 的 SERIAL</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> sequelize <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">class</span> <span class="pl-v">Collection</span> <span class="pl-k">extends</span> <span class="pl-v">Model</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-v">Collection</span><span class="pl-kos">.</span><span class="pl-en">init</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">uuid</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">type</span>: <span class="pl-v">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">UUID</span><span class="pl-kos">,</span>
    <span class="pl-c1">primaryKey</span>: <span class="pl-c1">true</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> sequelize <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre>
  </div>
  <p>如果你的模型根本没有主键,则可以使用&nbsp;<code>Model.removeAttribute('id');</code></p>
  <h2><a id="user-content-外键" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/legacy.md#%E5%A4%96%E9%94%AE" aria-hidden="true"></a>外键</h2>
  <div class="highlight highlight-source-js">
<pre><span class="pl-c">// 1:1</span>
<span class="pl-v">Organization</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">User</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">foreignKey</span>: <span class="pl-s">'owner_id'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">hasOne</span><span class="pl-kos">(</span><span class="pl-v">Organization</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">foreignKey</span>: <span class="pl-s">'owner_id'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// 1:M</span>
<span class="pl-v">Project</span><span class="pl-kos">.</span><span class="pl-en">hasMany</span><span class="pl-kos">(</span><span class="pl-v">Task</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">foreignKey</span>: <span class="pl-s">'tasks_pk'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Task</span><span class="pl-kos">.</span><span class="pl-en">belongsTo</span><span class="pl-kos">(</span><span class="pl-v">Project</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">foreignKey</span>: <span class="pl-s">'tasks_pk'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// N:M</span>
<span class="pl-v">User</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">Role</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-s">'user_has_roles'</span><span class="pl-kos">,</span> <span class="pl-c1">foreignKey</span>: <span class="pl-s">'user_role_user_id'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Role</span><span class="pl-kos">.</span><span class="pl-en">belongsToMany</span><span class="pl-kos">(</span><span class="pl-v">User</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">through</span>: <span class="pl-s">'user_has_roles'</span><span class="pl-kos">,</span> <span class="pl-c1">foreignKey</span>: <span class="pl-s">'roles_identifier'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;<br /><br /><br /></span></pre>
    <h1>Migrations - 迁移</h1>
    <p>就像你使用<a href="https://en.wikipedia.org/wiki/Version_control" rel="nofollow">版本控制</a>&nbsp;如&nbsp;<a href="https://en.wikipedia.org/wiki/Git" rel="nofollow">Git</a>&nbsp;来管理源代码的更改一样,你可以使用迁移来跟踪数据库的更改. 通过迁移,你可以将现有的数据库转移到另一个状态,反之亦然:这些状态转换将保存在迁移文件中,它们描述了如何进入新状态以及如何还原更改以恢复旧状态.</p>
    <p>你将需要&nbsp;<a href="https://github.com/sequelize/cli">Sequelize CLI</a>. CLI支持迁移和项目引导.</p>
    <p>Sequelize 中的 Migration 是一个 javascript 文件,它导出两个函数&nbsp;<code>up</code>&nbsp;和&nbsp;<code>down</code>,这些函数指示如何执行迁移和撤消它. 你可以手动定义这些功能,但不必手动调用它们; 它们将由 CLI 自动调用. 在这些函数中,你应该借助&nbsp;<code>sequelize.query</code>&nbsp;以及 Sequelize 提供给你的其他任何方法,简单地执行所需的任何查询. 除此之外,没有其他神奇的事情.</p>
    <h2><a id="user-content-安装-cli" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/migrations.md#%E5%AE%89%E8%A3%85-cli" aria-hidden="true"></a>安装 CLI</h2>
    <p>要安装 Sequelize CLI,请执行以下操作：</p>
    <pre lang="text"><code>npm install --save-dev sequelize-cli
</code></pre>
    <p>有关详细信息,请参见&nbsp;<a href="https://github.com/sequelize/cli">CLI GitHub 库</a>.</p>
    <h2><a id="user-content-项目启动" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/migrations.md#%E9%A1%B9%E7%9B%AE%E5%90%AF%E5%8A%A8" aria-hidden="true"></a>项目启动</h2>
    <p>要创建一个空项目,你需要执行&nbsp;<code>init</code>&nbsp;命令</p>
    <pre lang="text"><code>npx sequelize-cli init
</code></pre>
    <p>这将创建以下文件夹</p>
    <ul>
      <li><code>config</code>, 包含配置文件,它告诉CLI如何连接数据库</li>
      <li><code>models</code>,包含你的项目的所有模型</li>
      <li><code>migrations</code>, 包含所有迁移文件</li>
      <li><code>seeders</code>, 包含所有种子文件</li>
    </ul>
    <h3><a id="user-content-结构" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/migrations.md#%E7%BB%93%E6%9E%84" aria-hidden="true"></a>结构</h3>
    <p>在继续进行之前,我们需要告诉 CLI 如何连接到数据库. 为此,可以打开默认配置文件&nbsp;<code>config/config.json</code>. 看起来像这样:</p>
    <div class="highlight highlight-source-json">
<pre>{
  <span class="pl-s"><span class="pl-pds">"</span>development<span class="pl-pds">"</span></span>: {
    <span class="pl-s"><span class="pl-pds">"</span>username<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>root<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>password<span class="pl-pds">"</span></span>: <span class="pl-c1">null</span>,
    <span class="pl-s"><span class="pl-pds">"</span>database<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>database_development<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>host<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>127.0.0.1<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>dialect<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>mysql<span class="pl-pds">"</span></span>
  },
  <span class="pl-s"><span class="pl-pds">"</span>test<span class="pl-pds">"</span></span>: {
    <span class="pl-s"><span class="pl-pds">"</span>username<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>root<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>password<span class="pl-pds">"</span></span>: <span class="pl-c1">null</span>,
    <span class="pl-s"><span class="pl-pds">"</span>database<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>database_production<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>host<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>127.0.0.1<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>dialect<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>mysql<span class="pl-pds">"</span></span>
  },
  <span class="pl-s"><span class="pl-pds">"</span>production<span class="pl-pds">"</span></span>: {
    <span class="pl-s"><span class="pl-pds">"</span>username<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>root<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>password<span class="pl-pds">"</span></span>: <span class="pl-c1">null</span>,
    <span class="pl-s"><span class="pl-pds">"</span>database<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>database_test<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>host<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>127.0.0.1<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>dialect<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>mysql<span class="pl-pds">"</span></span>
  }
}</pre>
    </div>
    <p>请注意,默认情况下,Sequelize CLI 假定使用 mysql. 如果你使用其他方言,则需要更改&nbsp;<code>"dialect"</code>&nbsp;参数的内容.</p>
    <p>现在编辑此文件并设置正确的数据库凭据和方言.对象的键(例如 "development")用于&nbsp;<code>model/index.js</code>&nbsp;以匹配&nbsp;<code>process.env.NODE_ENV</code>(当未定义时,默认值是 "development").</p>
    <p>Sequelize 将为每个方言使用默认的连接端口(例如,对于postgres,它是端口5432). 如果需要指定其他端口,请使用&nbsp;<code>port</code>&nbsp;字段(默认情况下它不在 config/config.js 中,但你可以简单地添加它).</p>
    <p><strong>注意:</strong>&nbsp;<em>如果你的数据库还不存在,你可以调用&nbsp;<code>db:create</code>&nbsp;命令. 通过正确的访问,它将为你创建该数据库.</em></p>
    <h2><a id="user-content-创建第一个模型和迁移" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/migrations.md#%E5%88%9B%E5%BB%BA%E7%AC%AC%E4%B8%80%E4%B8%AA%E6%A8%A1%E5%9E%8B%E5%92%8C%E8%BF%81%E7%A7%BB" aria-hidden="true"></a>创建第一个模型(和迁移)</h2>
    <p>一旦你正确配置了CLI配置文件,你就可以首先创建迁移. 它像执行一个简单的命令一样简单.</p>
    <p>我们将使用&nbsp;<code>model:generate</code>&nbsp;命令. 此命令需要两个选项</p>
    <ul>
      <li><code>name</code>: 模型的名称</li>
      <li><code>attributes</code>: 模型的属性列表</li>
    </ul>
    <p>让我们创建一个名叫&nbsp;<code>User</code>&nbsp;的模型</p>
    <pre lang="text"><code>npx sequelize-cli model:generate --name User --attributes firstName:string,lastName:string,email:string
</code></pre>
    <p>这将发生以下事情</p>
    <ul>
      <li>在&nbsp;<code>models</code>&nbsp;文件夹中创建了一个&nbsp;<code>user</code>&nbsp;模型文件;</li>
      <li>在&nbsp;<code>migrations</code>&nbsp;文件夹中创建了一个名字像&nbsp;<code>XXXXXXXXXXXXXX-create-user.js</code>&nbsp;的迁移文件.</li>
    </ul>
    <p><strong>注意:</strong>&nbsp;_Sequelize 将只使用模型文件,它是表描述.另一边,迁移文件是该模型的更改,或更具体的是说 CLI 所使用的表. 处理迁移,如提交或日志,以进行数据库的某些更改. _</p>
    <h2><a id="user-content-运行迁移" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/migrations.md#%E8%BF%90%E8%A1%8C%E8%BF%81%E7%A7%BB" aria-hidden="true"></a>运行迁移</h2>
    <p>直到这一步,CLI没有将任何东西插入数据库. 我们刚刚为我们的第一个模型&nbsp;<code>User</code>&nbsp;创建了必需的模型和迁移文件. 现在要在数据库中实际创建该表,需要运行&nbsp;<code>db:migrate</code>&nbsp;命令.</p>
    <pre lang="text"><code>npx sequelize-cli db:migrate
</code></pre>
    <p>此命令将执行这些步骤</p>
    <ul>
      <li>将在数据库中确保一个名为&nbsp;<code>SequelizeMeta</code>&nbsp;的表. 此表用于记录在当前数据库上运行的迁移</li>
      <li>开始寻找尚未运行的任何迁移文件. 这可以通过检查&nbsp;<code>SequelizeMeta</code>&nbsp;表. 在这个例子中,它将运行我们在最后一步中创建的&nbsp;<code>XXXXXXXXXXXXXX-create-user.js</code>&nbsp;迁移,.</li>
      <li>创建一个名为&nbsp;<code>Users</code>&nbsp;的表,其中包含其迁移文件中指定的所有列.</li>
    </ul>
    <h2><a id="user-content-撤消迁移" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/migrations.md#%E6%92%A4%E6%B6%88%E8%BF%81%E7%A7%BB" aria-hidden="true"></a>撤消迁移</h2>
    <p>现在我们的表已创建并保存在数据库中. 通过迁移,只需运行命令即可恢复为旧状态.</p>
    <p>你可以使用&nbsp;<code>db:migrate:undo</code>,这个命令将会恢复最近的迁移.</p>
    <pre lang="text"><code>npx sequelize-cli db:migrate:undo
</code></pre>
    <p>通过使用&nbsp;<code>db:migrate:undo:all</code>&nbsp;命令撤消所有迁移,可以恢复到初始状态. 你还可以通过将其名称传递到&nbsp;<code>--to</code>&nbsp;选项中来恢复到特定的迁移.</p>
    <pre lang="text"><code>npx sequelize-cli db:migrate:undo:all --to XXXXXXXXXXXXXX-create-posts.js
</code></pre>
    <h3><a id="user-content-创建第一个种子" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/migrations.md#%E5%88%9B%E5%BB%BA%E7%AC%AC%E4%B8%80%E4%B8%AA%E7%A7%8D%E5%AD%90" aria-hidden="true"></a>创建第一个种子</h3>
    <p>假设我们希望在默认情况下将一些数据插入到几个表中. 如果我们跟进前面的例子,我们可以考虑为&nbsp;<code>User</code>&nbsp;表创建演示用户.</p>
    <p>要管理所有数据迁移,你可以使用&nbsp;<code>seeders</code>. 种子文件是数据的一些变化,可用于使用样本数据或测试数据填充数据库表.</p>
    <p>让我们创建一个种子文件,它会将一个演示用户添加到我们的&nbsp;<code>User</code>&nbsp;表中.</p>
    <pre lang="text"><code>npx sequelize-cli seed:generate --name demo-user
</code></pre>
    <p>这个命令将会在&nbsp;<code>seeders</code>&nbsp;文件夹中创建一个种子文件.文件名看起来像是&nbsp;<code>XXXXXXXXXXXXXX-demo-user.js</code>,它遵循相同的&nbsp;<code>up/down</code>&nbsp;语义,如迁移文件.</p>
    <p>现在我们应该编辑这个文件,将演示用户插入<code>User</code>表.</p>
    <div class="highlight highlight-source-js">
<pre><span class="pl-smi">module</span><span class="pl-kos">.</span><span class="pl-c1">exports</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
  <span class="pl-en">up</span>: <span class="pl-kos">(</span><span class="pl-s1">queryInterface</span><span class="pl-kos">,</span> <span class="pl-v">Sequelize</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-s1">queryInterface</span><span class="pl-kos">.</span><span class="pl-en">bulkInsert</span><span class="pl-kos">(</span><span class="pl-s">'Users'</span><span class="pl-kos">,</span> <span class="pl-kos">[</span><span class="pl-kos">{</span>
      <span class="pl-c1">firstName</span>: <span class="pl-s">'John'</span><span class="pl-kos">,</span>
      <span class="pl-c1">lastName</span>: <span class="pl-s">'Doe'</span><span class="pl-kos">,</span>
      <span class="pl-c1">email</span>: <span class="pl-s">'example@example.com'</span><span class="pl-kos">,</span>
      <span class="pl-c1">createdAt</span>: <span class="pl-k">new</span> <span class="pl-v">Date</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
      <span class="pl-c1">updatedAt</span>: <span class="pl-k">new</span> <span class="pl-v">Date</span><span class="pl-kos">(</span><span class="pl-kos">)</span>
    <span class="pl-kos">}</span><span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-en">down</span>: <span class="pl-kos">(</span><span class="pl-s1">queryInterface</span><span class="pl-kos">,</span> <span class="pl-v">Sequelize</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-s1">queryInterface</span><span class="pl-kos">.</span><span class="pl-en">bulkDelete</span><span class="pl-kos">(</span><span class="pl-s">'Users'</span><span class="pl-kos">,</span> <span class="pl-c1">null</span><span class="pl-kos">,</span> <span class="pl-kos">{</span><span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span></pre>
    </div>
    <h2><a id="user-content-运行种子" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/migrations.md#%E8%BF%90%E8%A1%8C%E7%A7%8D%E5%AD%90" aria-hidden="true"></a>运行种子</h2>
    <p>在上一步中,你创建了一个种子文件. 但它还没有保存到数据库. 为此,我们需要运行一个简单的命令.</p>
    <pre lang="text"><code>npx sequelize-cli db:seed:all
</code></pre>
    <p>这将执行该种子文件,你将有一个演示用户插入&nbsp;<code>User</code>&nbsp;表.</p>
    <p><strong>注意:</strong>&nbsp;<em>与使用&nbsp;<code>SequelizeMeta</code>&nbsp;表的迁移不同,<code>Seeder</code>&nbsp;执行历史记录不会存储在任何地方. 如果你想更改此行为,请阅读&nbsp;<code>存储</code>&nbsp;部分</em></p>
    <h2><a id="user-content-撤销种子" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/migrations.md#%E6%92%A4%E9%94%80%E7%A7%8D%E5%AD%90" aria-hidden="true"></a>撤销种子</h2>
    <p>Seeders 如果使用了任何存储那么就可以被撤消. 有两个可用的命令</p>
    <p>如果你想撤消最近的种子</p>
    <pre lang="text"><code>npx sequelize-cli db:seed:undo
</code></pre>
    <p>如果你想撤消特定的种子</p>
    <pre lang="text"><code>npx sequelize-cli db:seed:undo --seed name-of-seed-as-in-data
</code></pre>
    <p>如果你想撤消所有的种子</p>
    <pre lang="text"><code>npx sequelize-cli db:seed:undo:all
</code></pre>
    <h2><a id="user-content-高级专题" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/migrations.md#%E9%AB%98%E7%BA%A7%E4%B8%93%E9%A2%98" aria-hidden="true"></a>高级专题</h2>
    <p>以下框架显示了一个典型的迁移文件.</p>
    <div class="highlight highlight-source-js">
<pre><span class="pl-smi">module</span><span class="pl-kos">.</span><span class="pl-c1">exports</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
  <span class="pl-en">up</span>: <span class="pl-kos">(</span><span class="pl-s1">queryInterface</span><span class="pl-kos">,</span> <span class="pl-v">Sequelize</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-c">// 转变为新状态的逻辑</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-en">down</span>: <span class="pl-kos">(</span><span class="pl-s1">queryInterface</span><span class="pl-kos">,</span> <span class="pl-v">Sequelize</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-c">// 恢复更改的逻辑</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre>
    </div>
    <p>我们可以使用&nbsp;<code>migration:generate</code>&nbsp;生成该文件. 这将在你的迁移文件夹中创建&nbsp;<code>xxx-migration-skeleton.js</code>.</p>
    <pre lang="text"><code>npx sequelize-cli migration:generate --name migration-skeleton
</code></pre>
    <p>传递的&nbsp;<code>queryInterface</code>&nbsp;对象可以用来修改数据库.&nbsp;<code>Sequelize</code>&nbsp;对象存储可用的数据类型,如&nbsp;<code>STRING</code>&nbsp;或&nbsp;<code>INTEGER</code>. 函数&nbsp;<code>up</code>&nbsp;或&nbsp;<code>down</code>&nbsp;应该返回一个&nbsp;<code>Promise</code>&nbsp;. 让我们来看一个例子</p>
    <div class="highlight highlight-source-js">
<pre><span class="pl-smi">module</span><span class="pl-kos">.</span><span class="pl-c1">exports</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
  <span class="pl-en">up</span>: <span class="pl-kos">(</span><span class="pl-s1">queryInterface</span><span class="pl-kos">,</span> <span class="pl-v">Sequelize</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-s1">queryInterface</span><span class="pl-kos">.</span><span class="pl-en">createTable</span><span class="pl-kos">(</span><span class="pl-s">'Person'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
      <span class="pl-c1">name</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
      <span class="pl-c1">isBetaMember</span>: <span class="pl-kos">{</span>
        <span class="pl-c1">type</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">BOOLEAN</span><span class="pl-kos">,</span>
        <span class="pl-c1">defaultValue</span>: <span class="pl-c1">false</span><span class="pl-kos">,</span>
        <span class="pl-c1">allowNull</span>: <span class="pl-c1">false</span>
      <span class="pl-kos">}</span>
    <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-en">down</span>: <span class="pl-kos">(</span><span class="pl-s1">queryInterface</span><span class="pl-kos">,</span> <span class="pl-v">Sequelize</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-s1">queryInterface</span><span class="pl-kos">.</span><span class="pl-en">dropTable</span><span class="pl-kos">(</span><span class="pl-s">'Person'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span></pre>
    </div>
    <p>以下是一个迁移示例,该迁移使用自动管理的事务来在数据库中执行两次更改,以确保成功执行所有指令或在发生故障时回滚所有指令：</p>
    <div class="highlight highlight-source-js">
<pre><span class="pl-smi">module</span><span class="pl-kos">.</span><span class="pl-c1">exports</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
  <span class="pl-en">up</span>: <span class="pl-kos">(</span><span class="pl-s1">queryInterface</span><span class="pl-kos">,</span> <span class="pl-v">Sequelize</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-s1">queryInterface</span><span class="pl-kos">.</span><span class="pl-c1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">transaction</span><span class="pl-kos">(</span><span class="pl-s1">t</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
      <span class="pl-k">return</span> <span class="pl-v">Promise</span><span class="pl-kos">.</span><span class="pl-en">all</span><span class="pl-kos">(</span><span class="pl-kos">[</span>
        <span class="pl-s1">queryInterface</span><span class="pl-kos">.</span><span class="pl-en">addColumn</span><span class="pl-kos">(</span><span class="pl-s">'Person'</span><span class="pl-kos">,</span> <span class="pl-s">'petName'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
          <span class="pl-c1">type</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span>
        <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">transaction</span>: <span class="pl-s1">t</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
        <span class="pl-s1">queryInterface</span><span class="pl-kos">.</span><span class="pl-en">addColumn</span><span class="pl-kos">(</span><span class="pl-s">'Person'</span><span class="pl-kos">,</span> <span class="pl-s">'favoriteColor'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
          <span class="pl-c1">type</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
        <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">transaction</span>: <span class="pl-s1">t</span> <span class="pl-kos">}</span><span class="pl-kos">)</span>
      <span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-en">down</span>: <span class="pl-kos">(</span><span class="pl-s1">queryInterface</span><span class="pl-kos">,</span> <span class="pl-v">Sequelize</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-s1">queryInterface</span><span class="pl-kos">.</span><span class="pl-c1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">transaction</span><span class="pl-kos">(</span><span class="pl-s1">t</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
      <span class="pl-k">return</span> <span class="pl-v">Promise</span><span class="pl-kos">.</span><span class="pl-en">all</span><span class="pl-kos">(</span><span class="pl-kos">[</span>
        <span class="pl-s1">queryInterface</span><span class="pl-kos">.</span><span class="pl-en">removeColumn</span><span class="pl-kos">(</span><span class="pl-s">'Person'</span><span class="pl-kos">,</span> <span class="pl-s">'petName'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">transaction</span>: <span class="pl-s1">t</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
        <span class="pl-s1">queryInterface</span><span class="pl-kos">.</span><span class="pl-en">removeColumn</span><span class="pl-kos">(</span><span class="pl-s">'Person'</span><span class="pl-kos">,</span> <span class="pl-s">'favoriteColor'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">transaction</span>: <span class="pl-s1">t</span> <span class="pl-kos">}</span><span class="pl-kos">)</span>
      <span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span></pre>
    </div>
    <p>下一个是具有外键的迁移示例. 你可以使用 references 来指定外键:</p>
    <div class="highlight highlight-source-js">
<pre><span class="pl-smi">module</span><span class="pl-kos">.</span><span class="pl-c1">exports</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
  <span class="pl-en">up</span>: <span class="pl-kos">(</span><span class="pl-s1">queryInterface</span><span class="pl-kos">,</span> <span class="pl-v">Sequelize</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-s1">queryInterface</span><span class="pl-kos">.</span><span class="pl-en">createTable</span><span class="pl-kos">(</span><span class="pl-s">'Person'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
      <span class="pl-c1">name</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
      <span class="pl-c1">isBetaMember</span>: <span class="pl-kos">{</span>
        <span class="pl-c1">type</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">BOOLEAN</span><span class="pl-kos">,</span>
        <span class="pl-c1">defaultValue</span>: <span class="pl-c1">false</span><span class="pl-kos">,</span>
        <span class="pl-c1">allowNull</span>: <span class="pl-c1">false</span>
      <span class="pl-kos">}</span><span class="pl-kos">,</span>
      <span class="pl-c1">userId</span>: <span class="pl-kos">{</span>
        <span class="pl-c1">type</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">INTEGER</span><span class="pl-kos">,</span>
        <span class="pl-c1">references</span>: <span class="pl-kos">{</span>
          <span class="pl-c1">model</span>: <span class="pl-kos">{</span>
            <span class="pl-c1">tableName</span>: <span class="pl-s">'users'</span><span class="pl-kos">,</span>
            <span class="pl-c1">schema</span>: <span class="pl-s">'schema'</span>
          <span class="pl-kos">}</span><span class="pl-kos">,</span>
          <span class="pl-c1">key</span>: <span class="pl-s">'id'</span>
        <span class="pl-kos">}</span><span class="pl-kos">,</span>
        <span class="pl-c1">allowNull</span>: <span class="pl-c1">false</span>
      <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-en">down</span>: <span class="pl-kos">(</span><span class="pl-s1">queryInterface</span><span class="pl-kos">,</span> <span class="pl-v">Sequelize</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-s1">queryInterface</span><span class="pl-kos">.</span><span class="pl-en">dropTable</span><span class="pl-kos">(</span><span class="pl-s">'Person'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre>
    </div>
    <p>下一个是使用 async/await 的迁移示例, 其中你通过手动管理的事务在新列上创建唯一索引：</p>
    <div class="highlight highlight-source-js">
<pre><span class="pl-smi">module</span><span class="pl-kos">.</span><span class="pl-c1">exports</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
  <span class="pl-k">async</span> <span class="pl-en">up</span><span class="pl-kos">(</span><span class="pl-s1">queryInterface</span><span class="pl-kos">,</span> <span class="pl-v">Sequelize</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">const</span> <span class="pl-s1">transaction</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">queryInterface</span><span class="pl-kos">.</span><span class="pl-c1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">transaction</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">try</span> <span class="pl-kos">{</span>
      <span class="pl-k">await</span> <span class="pl-s1">queryInterface</span><span class="pl-kos">.</span><span class="pl-en">addColumn</span><span class="pl-kos">(</span>
        <span class="pl-s">'Person'</span><span class="pl-kos">,</span>
        <span class="pl-s">'petName'</span><span class="pl-kos">,</span>
        <span class="pl-kos">{</span>
          <span class="pl-c1">type</span>: <span class="pl-v">Sequelize</span><span class="pl-kos">.</span><span class="pl-c1">DataTypes</span><span class="pl-kos">.</span><span class="pl-c1">STRING</span><span class="pl-kos">,</span>
        <span class="pl-kos">}</span><span class="pl-kos">,</span>
        <span class="pl-kos">{</span> transaction <span class="pl-kos">}</span>
      <span class="pl-kos">)</span><span class="pl-kos">;</span>
      <span class="pl-k">await</span> <span class="pl-s1">queryInterface</span><span class="pl-kos">.</span><span class="pl-en">addIndex</span><span class="pl-kos">(</span>
        <span class="pl-s">'Person'</span><span class="pl-kos">,</span>
        <span class="pl-s">'petName'</span><span class="pl-kos">,</span>
        <span class="pl-kos">{</span>
          <span class="pl-c1">fields</span>: <span class="pl-s">'petName'</span><span class="pl-kos">,</span>
          <span class="pl-c1">unique</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
          transaction<span class="pl-kos">,</span>
        <span class="pl-kos">}</span>
      <span class="pl-kos">)</span><span class="pl-kos">;</span>
      <span class="pl-k">await</span> <span class="pl-s1">transaction</span><span class="pl-kos">.</span><span class="pl-en">commit</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span> <span class="pl-k">catch</span> <span class="pl-kos">(</span><span class="pl-s1">err</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-k">await</span> <span class="pl-s1">transaction</span><span class="pl-kos">.</span><span class="pl-en">rollback</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
      <span class="pl-k">throw</span> <span class="pl-s1">err</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-k">async</span> <span class="pl-en">down</span><span class="pl-kos">(</span><span class="pl-s1">queryInterface</span><span class="pl-kos">,</span> <span class="pl-v">Sequelize</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">const</span> <span class="pl-s1">transaction</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">queryInterface</span><span class="pl-kos">.</span><span class="pl-c1">sequelize</span><span class="pl-kos">.</span><span class="pl-en">transaction</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">try</span> <span class="pl-kos">{</span>
      <span class="pl-k">await</span> <span class="pl-s1">queryInterface</span><span class="pl-kos">.</span><span class="pl-en">removeColumn</span><span class="pl-kos">(</span><span class="pl-s">'Person'</span><span class="pl-kos">,</span> <span class="pl-s">'petName'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> transaction <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
      <span class="pl-k">await</span> <span class="pl-s1">transaction</span><span class="pl-kos">.</span><span class="pl-en">commit</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span> <span class="pl-k">catch</span> <span class="pl-kos">(</span><span class="pl-s1">err</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-k">await</span> <span class="pl-s1">transaction</span><span class="pl-kos">.</span><span class="pl-en">rollback</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
      <span class="pl-k">throw</span> <span class="pl-s1">err</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span></pre>
    </div>
    <h3><a id="user-content-sequelizerc-文件" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/migrations.md#sequelizerc-%E6%96%87%E4%BB%B6" aria-hidden="true"></a><code>.sequelizerc</code>&nbsp;文件</h3>
    <p>这是一个特殊的配置文件. 它允许你指定通常作为参数传递给CLI的各种选项:</p>
    <ul>
      <li><code>env</code>: 在其中运行命令的环境</li>
      <li><code>config</code>: 配置文件的路径</li>
      <li><code>options-path</code>: 带有其他参数的 JSON 文件的路径</li>
      <li><code>migrations-path</code>: migrations 文件夹的路径</li>
      <li><code>seeders-path</code>: seeders 文件夹的路径</li>
      <li><code>models-path</code>: models 文件夹的路径</li>
      <li><code>url</code>: 要使用的数据库连接字符串. 替代使用 --config 文件</li>
      <li><code>debug</code>: 可用时显示各种调试信息</li>
    </ul>
    <p>在某些情况下,你可以使用它:</p>
    <ul>
      <li>你想要覆盖到&nbsp;<code>migrations</code>,&nbsp;<code>models</code>,&nbsp;<code>seeders</code>&nbsp;或&nbsp;<code>config</code>&nbsp;文件夹的路径.</li>
      <li>你想要重命名&nbsp;<code>config.json</code>&nbsp;成为别的名字比如&nbsp;<code>database.json</code></li>
    </ul>
    <p>还有更多的, 让我们看一下如何使用这个文件进行自定义配置.</p>
    <p>首先,让我们在项目的根目录中创建&nbsp;<code>.sequelizerc</code>&nbsp;文件,其内容如下：</p>
    <div class="highlight highlight-source-js">
<pre><span class="pl-c">// .sequelizerc</span>

<span class="pl-k">const</span> <span class="pl-s1">path</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'path'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-smi">module</span><span class="pl-kos">.</span><span class="pl-c1">exports</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
  <span class="pl-s">'config'</span>: <span class="pl-s1">path</span><span class="pl-kos">.</span><span class="pl-en">resolve</span><span class="pl-kos">(</span><span class="pl-s">'config'</span><span class="pl-kos">,</span> <span class="pl-s">'database.json'</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
  <span class="pl-s">'models-path'</span>: <span class="pl-s1">path</span><span class="pl-kos">.</span><span class="pl-en">resolve</span><span class="pl-kos">(</span><span class="pl-s">'db'</span><span class="pl-kos">,</span> <span class="pl-s">'models'</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
  <span class="pl-s">'seeders-path'</span>: <span class="pl-s1">path</span><span class="pl-kos">.</span><span class="pl-en">resolve</span><span class="pl-kos">(</span><span class="pl-s">'db'</span><span class="pl-kos">,</span> <span class="pl-s">'seeders'</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
  <span class="pl-s">'migrations-path'</span>: <span class="pl-s1">path</span><span class="pl-kos">.</span><span class="pl-en">resolve</span><span class="pl-kos">(</span><span class="pl-s">'db'</span><span class="pl-kos">,</span> <span class="pl-s">'migrations'</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span></pre>
    </div>
    <p>通过这个配置你告诉CLI:</p>
    <ul>
      <li>使用&nbsp;<code>config/database.json</code>&nbsp;文件来配置设置;</li>
      <li>使用&nbsp;<code>db/models</code>&nbsp;作为模型文件夹;</li>
      <li>使用&nbsp;<code>db/seeders</code>&nbsp;作为种子文件夹;</li>
      <li>使用&nbsp;<code>db/migrations</code>&nbsp;作为迁移文件夹;</li>
    </ul>
    <h3><a id="user-content-动态配置" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/migrations.md#%E5%8A%A8%E6%80%81%E9%85%8D%E7%BD%AE" aria-hidden="true"></a>动态配置</h3>
    <p>默认情况下,配置文件是一个名为&nbsp;<code>config.json</code>&nbsp;的 JSON 文件. 但是有时你需要动态配置,例如访问环境变量或执行其他代码来确定配置.</p>
    <p>值得庆幸的是,Sequelize CLI 可以从&nbsp;<code>.json</code>&nbsp;和&nbsp;<code>.js</code>&nbsp;文件中读取. 可以使用&nbsp;<code>.sequelizerc</code>&nbsp;文件来设置. 你只需提供&nbsp;<code>.js</code>&nbsp;文件的路径作为导出对象的&nbsp;<code>config</code>&nbsp;参数即可：</p>
    <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">path</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'path'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-smi">module</span><span class="pl-kos">.</span><span class="pl-c1">exports</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
  <span class="pl-s">'config'</span>: <span class="pl-s1">path</span><span class="pl-kos">.</span><span class="pl-en">resolve</span><span class="pl-kos">(</span><span class="pl-s">'config'</span><span class="pl-kos">,</span> <span class="pl-s">'config.js'</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre>
    </div>
    <p>现在,Sequelize CLI 将加载&nbsp;<code>config/config.js</code>&nbsp;以获取配置参数.</p>
    <p>一个&nbsp;<code>config/config.js</code>&nbsp;文件的例子</p>
    <div class="highlight highlight-source-js">
<pre><span class="pl-k">const</span> <span class="pl-s1">fs</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'fs'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-smi">module</span><span class="pl-kos">.</span><span class="pl-c1">exports</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
  <span class="pl-c1">development</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">username</span>: <span class="pl-s">'database_dev'</span><span class="pl-kos">,</span>
    <span class="pl-c1">password</span>: <span class="pl-s">'database_dev'</span><span class="pl-kos">,</span>
    <span class="pl-c1">database</span>: <span class="pl-s">'database_dev'</span><span class="pl-kos">,</span>
    <span class="pl-c1">host</span>: <span class="pl-s">'127.0.0.1'</span><span class="pl-kos">,</span>
    <span class="pl-c1">port</span>: <span class="pl-c1">3306</span><span class="pl-kos">,</span>
    <span class="pl-c1">dialect</span>: <span class="pl-s">'mysql'</span><span class="pl-kos">,</span>
    <span class="pl-c1">dialectOptions</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">bigNumberStrings</span>: <span class="pl-c1">true</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">test</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">username</span>: <span class="pl-s1">process</span><span class="pl-kos">.</span><span class="pl-c1">env</span><span class="pl-kos">.</span><span class="pl-c1">CI_DB_USERNAME</span><span class="pl-kos">,</span>
    <span class="pl-c1">password</span>: <span class="pl-s1">process</span><span class="pl-kos">.</span><span class="pl-c1">env</span><span class="pl-kos">.</span><span class="pl-c1">CI_DB_PASSWORD</span><span class="pl-kos">,</span>
    <span class="pl-c1">database</span>: <span class="pl-s1">process</span><span class="pl-kos">.</span><span class="pl-c1">env</span><span class="pl-kos">.</span><span class="pl-c1">CI_DB_NAME</span><span class="pl-kos">,</span>
    <span class="pl-c1">host</span>: <span class="pl-s">'127.0.0.1'</span><span class="pl-kos">,</span>
    <span class="pl-c1">port</span>: <span class="pl-c1">3306</span><span class="pl-kos">,</span>
    <span class="pl-c1">dialect</span>: <span class="pl-s">'mysql'</span><span class="pl-kos">,</span>
    <span class="pl-c1">dialectOptions</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">bigNumberStrings</span>: <span class="pl-c1">true</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">production</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">username</span>: <span class="pl-s1">process</span><span class="pl-kos">.</span><span class="pl-c1">env</span><span class="pl-kos">.</span><span class="pl-c1">PROD_DB_USERNAME</span><span class="pl-kos">,</span>
    <span class="pl-c1">password</span>: <span class="pl-s1">process</span><span class="pl-kos">.</span><span class="pl-c1">env</span><span class="pl-kos">.</span><span class="pl-c1">PROD_DB_PASSWORD</span><span class="pl-kos">,</span>
    <span class="pl-c1">database</span>: <span class="pl-s1">process</span><span class="pl-kos">.</span><span class="pl-c1">env</span><span class="pl-kos">.</span><span class="pl-c1">PROD_DB_NAME</span><span class="pl-kos">,</span>
    <span class="pl-c1">host</span>: <span class="pl-s1">process</span><span class="pl-kos">.</span><span class="pl-c1">env</span><span class="pl-kos">.</span><span class="pl-c1">PROD_DB_HOSTNAME</span><span class="pl-kos">,</span>
    <span class="pl-c1">port</span>: <span class="pl-s1">process</span><span class="pl-kos">.</span><span class="pl-c1">env</span><span class="pl-kos">.</span><span class="pl-c1">PROD_DB_PORT</span><span class="pl-kos">,</span>
    <span class="pl-c1">dialect</span>: <span class="pl-s">'mysql'</span><span class="pl-kos">,</span>
    <span class="pl-c1">dialectOptions</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">bigNumberStrings</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
      <span class="pl-c1">ssl</span>: <span class="pl-kos">{</span>
        <span class="pl-c1">ca</span>: <span class="pl-s1">fs</span><span class="pl-kos">.</span><span class="pl-en">readFileSync</span><span class="pl-kos">(</span><span class="pl-s1">__dirname</span> <span class="pl-c1">+</span> <span class="pl-s">'/mysql-ca-master.crt'</span><span class="pl-kos">)</span>
      <span class="pl-kos">}</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span></pre>
    </div>
    <p>上面的示例还显示了如何向配置中添加自定义方言参数.</p>
    <h3><a id="user-content-使用-babel" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/migrations.md#%E4%BD%BF%E7%94%A8-babel" aria-hidden="true"></a>使用 Babel</h3>
    <p>为了在你的迁移和 seeder 中实现更现代的构造,你可以简单地安装&nbsp;<code>babel-register</code>&nbsp;并在&nbsp;<code>.sequelizerc</code>&nbsp;开始时 require 它：</p>
    <pre lang="text"><code>npm i --save-dev babel-register
</code></pre>
    <div class="highlight highlight-source-js">
<pre><span class="pl-c">// .sequelizerc</span>

<span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">"babel-register"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">const</span> <span class="pl-s1">path</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'path'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-smi">module</span><span class="pl-kos">.</span><span class="pl-c1">exports</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
  <span class="pl-s">'config'</span>: <span class="pl-s1">path</span><span class="pl-kos">.</span><span class="pl-en">resolve</span><span class="pl-kos">(</span><span class="pl-s">'config'</span><span class="pl-kos">,</span> <span class="pl-s">'config.json'</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
  <span class="pl-s">'models-path'</span>: <span class="pl-s1">path</span><span class="pl-kos">.</span><span class="pl-en">resolve</span><span class="pl-kos">(</span><span class="pl-s">'models'</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
  <span class="pl-s">'seeders-path'</span>: <span class="pl-s1">path</span><span class="pl-kos">.</span><span class="pl-en">resolve</span><span class="pl-kos">(</span><span class="pl-s">'seeders'</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
  <span class="pl-s">'migrations-path'</span>: <span class="pl-s1">path</span><span class="pl-kos">.</span><span class="pl-en">resolve</span><span class="pl-kos">(</span><span class="pl-s">'migrations'</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre>
    </div>
    <p>当然,结果将取决于你的 babel 配置(例如在&nbsp;<code>.babelrc</code>&nbsp;文件中). 在<a href="https://babeljs.io/" rel="nofollow">babeljs.io</a>了解更多信息</p>
    <h3><a id="user-content-安全提示" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/migrations.md#%E5%AE%89%E5%85%A8%E6%8F%90%E7%A4%BA" aria-hidden="true"></a>安全提示</h3>
    <p>使用环境变量进行配置设置. 这是因为诸如密码之类的机密绝不应该是源代码的一部分(尤其是不要提交给版本控制).</p>
    <h3><a id="user-content-存储" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/migrations.md#%E5%AD%98%E5%82%A8" aria-hidden="true"></a>存储</h3>
    <p>你可以使用三种类型的存储：<code>sequelize</code>,<code>json</code>和<code>none</code>.</p>
    <ul>
      <li><code>sequelize</code>&nbsp;: 将迁移和种子存储在 sequelize 数据库的表中</li>
      <li><code>json</code>&nbsp;: 将迁移和种子存储在 json 文件中</li>
      <li><code>none</code>&nbsp;: 不存储任何迁移/种子</li>
    </ul>
    <h4><a id="user-content-迁移存储" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/migrations.md#%E8%BF%81%E7%A7%BB%E5%AD%98%E5%82%A8" aria-hidden="true"></a>迁移存储</h4>
    <p>默认情况下,CLI 将在数据库中创建一个名为&nbsp;<code>SequelizeMeta</code>&nbsp;的表,其中包含每个执行的迁移的条目. 要更改此行为,可以将三个参数添加到配置文件中. 使用&nbsp;<code>migrationStorage</code>,你可以选择用于迁移的存储类型. 如果选择&nbsp;<code>json</code>,则可以使用&nbsp;<code>migrationStoragePath</code>&nbsp;指定文件的路径,否则 CLI 将写入文件&nbsp;<code>sequelize-meta.json</code>. 如果你想使用&nbsp;<code>sequelize</code>&nbsp;将信息保留在数据库中,但又想使用其他表,则可以使用&nbsp;<code>migrationStorageTableName</code>&nbsp;来更改表名. 你还可以通过提供&nbsp;<code>migrationStorageTableSchema</code>&nbsp;属性来为&nbsp;<code>SequelizeMeta</code>&nbsp;表定义不同的架构.</p>
    <div class="highlight highlight-source-json">
<pre>{
  <span class="pl-s"><span class="pl-pds">"</span>development<span class="pl-pds">"</span></span>: {
    <span class="pl-s"><span class="pl-pds">"</span>username<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>root<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>password<span class="pl-pds">"</span></span>: <span class="pl-c1">null</span>,
    <span class="pl-s"><span class="pl-pds">"</span>database<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>database_development<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>host<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>127.0.0.1<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>dialect<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>mysql<span class="pl-pds">"</span></span>,

    <span class="pl-ii">//</span> <span class="pl-ii">使用其他存储类型.</span> <span class="pl-ii">默认</span>: <span class="pl-ii">sequelize</span>
    <span class="pl-s"><span class="pl-pds">"</span>migrationStorage<span class="pl-pds">"</span></span><span class="pl-ii">:</span> <span class="pl-s"><span class="pl-pds">"</span>json<span class="pl-pds">"</span></span>,

    <span class="pl-ii">//</span> <span class="pl-ii">使用其他文件名.</span> <span class="pl-ii">默认</span>: <span class="pl-ii">sequelize-meta.json</span>
    <span class="pl-s"><span class="pl-pds">"</span>migrationStoragePath<span class="pl-pds">"</span></span><span class="pl-ii">:</span> <span class="pl-s"><span class="pl-pds">"</span>sequelizeMeta.json<span class="pl-pds">"</span></span>,

    <span class="pl-ii">//</span> <span class="pl-ii">使用其他表格名称.</span> <span class="pl-ii">默认</span>: <span class="pl-ii">SequelizeMeta</span>
    <span class="pl-s"><span class="pl-pds">"</span>migrationStorageTableName<span class="pl-pds">"</span></span><span class="pl-ii">:</span> <span class="pl-s"><span class="pl-pds">"</span>sequelize_meta<span class="pl-pds">"</span></span>,

    <span class="pl-ii">//</span> <span class="pl-ii">对</span> <span class="pl-ii">SequelizeMeta</span> <span class="pl-ii">表使用其他架构</span>
    <span class="pl-s"><span class="pl-pds">"</span>migrationStorageTableSchema<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>custom_schema<span class="pl-pds">"</span></span>
  }
}</pre>
    </div>
    <p><strong>Note:</strong>&nbsp;<em>不建议将&nbsp;<code>none</code>&nbsp;存储作为迁移存储. 如果你决定使用它,请注意没有任何迁移进行或未运行的记录的含义.</em></p>
    <h4><a id="user-content-种子储存" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/migrations.md#%E7%A7%8D%E5%AD%90%E5%82%A8%E5%AD%98" aria-hidden="true"></a>种子储存</h4>
    <p>默认情况下,CLI 不会保存任何已执行的种子. 如果选择更改此行为(！),则可以在配置文件中使用&nbsp;<code>seederStorage</code>&nbsp;来更改存储类型. 如果选择&nbsp;<code>json</code>,则可以使用&nbsp;<code>seederStoragePath</code>&nbsp;指定文件的路径,否则 CLI 将写入文件&nbsp;<code>sequelize-data.json</code>. 如果要使用&nbsp;<code>sequelize</code>&nbsp;将信息保留在数据库中,则可以使用&nbsp;<code>seederStorageTableName</code>&nbsp;指定表名,否则它将默认为&nbsp;<code>SequelizeData</code>.</p>
    <div class="highlight highlight-source-json">
<pre>{
  <span class="pl-s"><span class="pl-pds">"</span>development<span class="pl-pds">"</span></span>: {
    <span class="pl-s"><span class="pl-pds">"</span>username<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>root<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>password<span class="pl-pds">"</span></span>: <span class="pl-c1">null</span>,
    <span class="pl-s"><span class="pl-pds">"</span>database<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>database_development<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>host<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>127.0.0.1<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>dialect<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>mysql<span class="pl-pds">"</span></span>,
    <span class="pl-ii">//</span> <span class="pl-ii">使用其他存储.</span> <span class="pl-ii">默认</span>: <span class="pl-ii">none</span>
    <span class="pl-s"><span class="pl-pds">"</span>seederStorage<span class="pl-pds">"</span></span><span class="pl-ii">:</span> <span class="pl-s"><span class="pl-pds">"</span>json<span class="pl-pds">"</span></span>,
    <span class="pl-ii">//</span> <span class="pl-ii">使用其他文件名称.</span> <span class="pl-ii">默认</span>: <span class="pl-ii">sequelize-data.json</span>
    <span class="pl-s"><span class="pl-pds">"</span>seederStoragePath<span class="pl-pds">"</span></span><span class="pl-ii">:</span> <span class="pl-s"><span class="pl-pds">"</span>sequelizeData.json<span class="pl-pds">"</span></span>,
    <span class="pl-ii">//</span> <span class="pl-ii">使用其他表格名称.</span> <span class="pl-ii">默认</span>: <span class="pl-ii">SequelizeData</span>
    <span class="pl-s"><span class="pl-pds">"</span>seederStorageTableName<span class="pl-pds">"</span></span><span class="pl-ii">:</span> <span class="pl-s"><span class="pl-pds">"</span>sequelize_data<span class="pl-pds">"</span></span>
  }
}</pre>
    </div>
    <h3><a id="user-content-配置连接字符串" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/migrations.md#%E9%85%8D%E7%BD%AE%E8%BF%9E%E6%8E%A5%E5%AD%97%E7%AC%A6%E4%B8%B2" aria-hidden="true"></a>配置连接字符串</h3>
    <p>配置连接字符串作为配置文件定义数据库的&nbsp;<code>--config</code>&nbsp;参数的替代方法,可以使用&nbsp;<code>--url</code>&nbsp;参数来传递连接字符串. 例如：</p>
    <pre lang="text"><code>npx sequelize-cli db:migrate --url 'mysql://root:password@mysql_host.com/database_name'
</code></pre>
    <h3><a id="user-content-程序用法" class="anchor" href="https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/other-topics/migrations.md#%E7%A8%8B%E5%BA%8F%E7%94%A8%E6%B3%95" aria-hidden="true"></a>程序用法</h3>
    <p>程序用法 Sequelize 有一个名为&nbsp;<a href="https://github.com/sequelize/umzug">umzug</a>&nbsp;的姊妹库,用于以编程方式处理迁移任务的执行和日志记录.</p>
    <pre>&nbsp;</pre>
  </div>
</div>
</body>
</html>
